From 442498d5305ed1b66d1eef56d2f8866f52fac1f4 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Sat, 16 Mar 2024 15:38:10 -0700 Subject: [PATCH 01/18] Collection expressions: require Add method callable with single argument for class and struct types that do not use [CollectionBuilder] --- ...onInitializerTests_CollectionExpression.cs | 10 - .../Portable/Binder/Binder_Conversions.cs | 82 +- .../Semantics/Conversions/Conversions.cs | 2 +- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/ErrorFacts.cs | 1 + .../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 + .../Semantics/CollectionExpressionTests.cs | 2387 +++++++++++++++-- 20 files changed, 2309 insertions(+), 242 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs index 37e3bdc1f4dac..9236edbf08487 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs @@ -5270,16 +5270,6 @@ public void Add(string s) { } { OutputKind = OutputKind.DynamicallyLinkedLibrary, }, - FixedState = - { - ExpectedDiagnostics = - { - // /0/Test0.cs(6,26): error CS1503: Argument 1: cannot convert from 'object' to 'string' - DiagnosticResult.CompilerError("CS1503").WithSpan(6, 26, 6, 36).WithArguments("1", "object", "string"), - // /0/Test0.cs(6,26): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection.Add(string)'. - DiagnosticResult.CompilerError("CS9215").WithSpan(6, 26, 6, 36).WithArguments("object", "MyCollection.Add(string)"), - } - } }.RunAsync(); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 6b07dc19faac5..0924b078e972e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1285,6 +1285,85 @@ static bool bindInvocationExpressionContinued( } } + internal bool HasCollectionExpressionAddMethod(SyntaxNode syntax, TypeSymbol targetType) + { + const string methodName = "Add"; + var useSiteInfo = CompoundUseSiteInfo.Discarded; + + var lookupResult = LookupResult.GetInstance(); + LookupInstanceMember(lookupResult, targetType, leftIsBaseReference: false, rightName: methodName, rightArity: 0, invoked: true, ref useSiteInfo); + bool anyApplicable = lookupResult.IsMultiViable && + lookupResult.Symbols.Any(s => s is MethodSymbol m && isApplicableAddMethod(m, expectingExtensionMethod: false)); + lookupResult.Free(); + if (anyApplicable) + { + return true; + } + + var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; + foreach (var scope in new ExtensionMethodScopes(this)) + { + var methodGroup = MethodGroup.GetInstance(); + PopulateExtensionMethodsFromSingleBinder(scope, methodGroup, syntax, implicitReceiver, rightName: methodName, typeArgumentsWithAnnotations: default, BindingDiagnosticBag.Discarded); + anyApplicable = methodGroup.Methods.Any(m => isApplicableAddMethod(m, expectingExtensionMethod: true)); + methodGroup.Free(); + if (anyApplicable) + { + return true; + } + } + + return false; + + static bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMethod) + { + if (method.IsStatic != expectingExtensionMethod) + { + return false; + } + + var parameters = method.Parameters; + int valueIndex = expectingExtensionMethod ? 1 : 0; + int requiredLength = valueIndex + 1; + if (parameters.Length < requiredLength) + { + return false; + } + + // Any trailing parameters must be optional or params. + for (int i = requiredLength; i < parameters.Length; i++) + { + if (parameters[i] is { IsOptional: false, IsParams: false }) + { + return false; + } + } + + // Value parameter must be by value, in, or ref readonly. + if (parameters[valueIndex].RefKind is not (RefKind.None or RefKind.In or RefKind.RefReadOnlyParameter)) + { + return false; + } + + // If the method is generic, can the type arguments be inferred from the one or two arguments? + var typeParameters = method.TypeParameters; + if (typeParameters.Length > 0) + { + var usedParameterTypes = parameters.Slice(0, requiredLength).SelectAsArray(p => p.Type); + foreach (var typeParameter in typeParameters) + { + if (!usedParameterTypes.Any((parameterType, typeParameter) => parameterType.ContainsTypeParameter(typeParameter), typeParameter)) + { + // The type parameter does not appear in any of the parameter types. + return false; + } + } + } + + return true; + } + } + /// /// If the element is from a collection type where elements are added with collection initializers, /// return the argument to the collection initializer Add method or null if the element is not a @@ -1422,8 +1501,9 @@ private void GenerateImplicitConversionErrorForCollectionExpression( } if (elements.Length > 0 && - !HasCollectionExpressionApplicableAddMethod(node.Syntax, targetType, elementType, addMethods: out _, diagnostics)) + !HasCollectionExpressionAddMethod(node.Syntax, targetType)) { + Error(diagnostics, ErrorCode.ERR_CollectionExpressionMissingAdd_New, node.Syntax, targetType); reportedErrors = true; } } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 3332390061a99..f80409e0c41bc 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -194,7 +194,7 @@ protected override Conversion GetCollectionExpressionConversion( } if (elements.Length > 0 && - !_binder.HasCollectionExpressionApplicableAddMethod(syntax, targetType, elementType, addMethods: out _, BindingDiagnosticBag.Discarded)) + !_binder.HasCollectionExpressionAddMethod(syntax, targetType)) { return Conversion.NoConversion; } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 1c597710b3960..aa2a28d28aad8 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6865,6 +6865,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + The CollectionBuilderAttribute builder type must be a non-generic class or struct. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 70c3ed6d8b861..dec96cc921739 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2301,6 +2301,7 @@ internal enum ErrorCode ERR_ParamsCollectionMissingConstructor = 9228, ERR_NoModifiersOnUsing = 9229, + ERR_CollectionExpressionMissingAdd_New = 9230, // PROTOTYPE: Replace ERR_CollectionExpressionMissingAdd. #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index b4eaef25f8e7a..fdfc3b57c4140 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2431,6 +2431,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_ParamsCollectionExtensionAddMethod: case ErrorCode.ERR_ParamsCollectionMissingConstructor: case ErrorCode.ERR_NoModifiersOnUsing: + case ErrorCode.ERR_CollectionExpressionMissingAdd_New: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 52bc7a06848ef..36a5e56eb6ddc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 31fdb8ad5d94e..7964ca18eb710 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 46d2302cf07e3..8d07db6aa567e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 21d95c543a69c..e005b35c31972 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 4b6f9d4393503..7f59d0885d7b9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index d22e46da8f2c8..9136c3ded5de2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 3c3e4232b34f0..e697b5b6c02ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 236da182cee77..46a02b0045eff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index ed4a82cea33ad..bbd6e3dcf71ab 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 197239919e8d6..b630085e440cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 44f14a30f0b80..1f229849cb79d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 0983b4f8fc93c..fbea061e7abef 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index ac7f52744cd5c..d8e596a36d9ae 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -447,6 +447,11 @@ Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. + + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. + + Collection expression type must have an applicable constructor that can be called with no arguments. Collection expression type must have an applicable constructor that can be called with no arguments. diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 892925207389d..938a600e7fbc5 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -3779,12 +3779,6 @@ static void Main() comp.VerifyEmitDiagnostics( // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1), - // 1.cs(6,23): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'List.Add(int)'. - // List l = [1]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("object", "System.Collections.Generic.List.Add(int)").WithLocation(6, 23), - // 1.cs(6,23): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // List l = [1]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1]").WithArguments("1", "object", "int").WithLocation(6, 23), // 1.cs(7,16): error CS9174: Cannot initialize type 'IA' with a collection expression because the type is not constructible. // IA a = [2]; Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[2]").WithArguments("System.Collections.Generic.IA").WithLocation(7, 16), @@ -3849,12 +3843,6 @@ static void Main() comp.VerifyEmitDiagnostics( // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1), - // 1.cs(7,23): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'List.Add(int)'. - // List l = [1]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("object", "System.Collections.Generic.List.Add(int)").WithLocation(7, 23), - // 1.cs(7,23): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // List l = [1]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1]").WithArguments("1", "object", "int").WithLocation(7, 23), // 1.cs(8,29): error CS9174: Cannot initialize type 'IEquatable' with a collection expression because the type is not constructible. // IEquatable e = [2]; Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[2]").WithArguments("System.IEquatable").WithLocation(8, 29)); @@ -4518,39 +4506,39 @@ static void Main() // (7,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [default]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(7, 13), - // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [default]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(7, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(7, 13), // (8,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [null]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(8, 13), - // (8,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (8,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [null]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(8, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(8, 13), // (8,14): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type // s = [null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(8, 14), // (9,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = ['a']; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(9, 13), - // (9,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (9,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(9, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(9, 13), // (10,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [1]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(10, 13), - // (10,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (10,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(10, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(10, 13), // (10,14): error CS0029: Cannot implicitly convert type 'int' to 'char' // s = [1]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(10, 14), // (11,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [..""]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"[..""""]").WithArguments("string", "0").WithLocation(11, 13), - // (11,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (11,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [..""]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(11, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(11, 13)); } [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] @@ -4579,42 +4567,42 @@ static void Main() // (6,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)[default]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(6, 21), - // (6,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (6,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[default]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(6, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(6, 21), // (6,22): error CS8716: There is no target type for the default literal. // _ = (string)[default]; Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(6, 22), // (7,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)[null]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(7, 21), - // (7,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (7,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[null]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(7, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(7, 21), // (7,22): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type // _ = (string)[null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(7, 22), // (8,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)['a']; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(8, 21), - // (8,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (8,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)['a']; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(8, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(8, 21), // (9,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)[1]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(9, 21), - // (9,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (9,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[1]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(9, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(9, 21), // (9,22): error CS0029: Cannot implicitly convert type 'int' to 'char' // _ = (string)[1]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(9, 22), // (10,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)[..""]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"[..""""]").WithArguments("string", "0").WithLocation(10, 21), - // (10,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (10,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[..""]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(10, 21)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(10, 21)); } [Fact] @@ -5300,9 +5288,9 @@ struct S : IEnumerable """; var comp = CreateCompilation(new[] { sourceA, sourceB2 }); comp.VerifyEmitDiagnostics( - // 1.cs(2,5): error CS1061: 'S' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'S' could be found (are you missing a using directive or an assembly reference?) + // 1.cs(2,5): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, 2]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2]").WithArguments("S", "Add").WithLocation(2, 5), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2]").WithArguments("S").WithLocation(2, 5), // 1.cs(3,9): error CS9212: Spread operator '..' cannot operate on variables of type 'object' because 'object' does not contain a public instance or extension definition for 'GetEnumerator' // s = [.. new object()]; Diagnostic(ErrorCode.ERR_SpreadMissingMember, "new object()").WithArguments("object", "GetEnumerator").WithLocation(3, 9)); @@ -5330,13 +5318,7 @@ public void Add(int i) { } Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("C", "0").WithLocation(3, 5), // (4,5): error CS1729: 'C' does not contain a constructor that takes 0 arguments // c = [1, 2]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1, 2]").WithArguments("C", "0").WithLocation(4, 5), - // (4,5): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int)'. - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "C.Add(int)").WithLocation(4, 5), - // (4,5): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(4, 5)); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1, 2]").WithArguments("C", "0").WithLocation(4, 5)); } [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] @@ -5408,17 +5390,13 @@ static void Main() object o; c = [1, 2]; o = (C)[3, 4]; + c.Report(); + o.Report(); } } """; var comp = CreateCompilation(new[] { sourceA, sourceB2 }); - comp.VerifyEmitDiagnostics( - // 1.cs(7,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int)'. - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "C.Add(int)").WithLocation(7, 13), - // 1.cs(7,13): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(7, 13)); + CompileAndVerify(new[] { sourceA, sourceB2, s_collectionExtensions }, expectedOutput: "[1, 2], [3, 4], "); } [Fact] @@ -5525,36 +5503,30 @@ public void CollectionInitializerType_08A() string source = """ using System; using System.Collections; + using System.Collections.Generic; struct S0 : IEnumerable { - public void Add(T t) { } - IEnumerator IEnumerable.GetEnumerator() => throw null; + private List _list; + public void Add(T t) { GetList().Add(t); } + IEnumerator IEnumerable.GetEnumerator() => GetList().GetEnumerator(); + private List GetList() => _list ??= new(); } class Program { - static void M0() + static void Main() { object o = (S0)[]; + o.Report(); o = (S0)[1, 2]; + o.Report(); S0 s = []; + s.Report(); s = [1, 2]; + s.Report(); } } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (13,22): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'S0.Add(int)'. - // o = (S0)[1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "S0.Add(int)").WithLocation(13, 22), - // (13,22): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // o = (S0)[1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(13, 22), - // (15,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'S0.Add(int)'. - // s = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "S0.Add(int)").WithLocation(15, 13), - // (15,13): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // s = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(15, 13)); + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [1, 2], [], [1, 2], "); } [Fact] @@ -5778,12 +5750,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,15): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(IA)'. + // (15,36): error CS0121: The call is ambiguous between the following methods or properties: 'C.Add(IA)' and 'C.Add(IB)' // C c = [(IA)null, (IB)null, new AB()]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[(IA)null, (IB)null, new AB()]").WithArguments("object", "C.Add(IA)").WithLocation(15, 15), - // (15,15): error CS1503: Argument 1: cannot convert from 'object' to 'IA' - // C c = [(IA)null, (IB)null, new AB()]; - Diagnostic(ErrorCode.ERR_BadArgType, "[(IA)null, (IB)null, new AB()]").WithArguments("1", "object", "IA").WithLocation(15, 15)); + Diagnostic(ErrorCode.ERR_AmbigCall, "new AB()").WithArguments("C.Add(IA)", "C.Add(IB)").WithLocation(15, 36)); } [Fact] @@ -5813,12 +5782,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (18,15): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'Extensions.Add(C, IA)'. - // C c = [(IA)null, (IB)null, new AB()]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[(IA)null, (IB)null, new AB()]").WithArguments("object", "Extensions.Add(C, IA)").WithLocation(18, 15), - // (18,15): error CS1503: Argument 2: cannot convert from 'object' to 'IA' + // (18,36): error CS0121: The call is ambiguous between the following methods or properties: 'Extensions.Add(C, IA)' and 'Extensions.Add(C, IB)' // C c = [(IA)null, (IB)null, new AB()]; - Diagnostic(ErrorCode.ERR_BadArgType, "[(IA)null, (IB)null, new AB()]").WithArguments("2", "object", "IA").WithLocation(18, 15)); + Diagnostic(ErrorCode.ERR_AmbigCall, "new AB()").WithArguments("Extensions.Add(C, IA)", "Extensions.Add(C, IB)").WithLocation(18, 36)); } [Fact] @@ -5843,9 +5809,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (13,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'S.Add(int, int)'. + // (13,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("object", "S.Add(int, int)").WithLocation(13, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(13, 13)); } [Fact] @@ -5872,9 +5838,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'int'. The best overloaded method is 'S.Add(int, int)'. + // (15,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("int", "S.Add(int, int)").WithLocation(15, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(15, 13)); } [Fact] @@ -5904,9 +5870,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (18,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'int'. The best overloaded method is 'Extensions.Add(S, T, T)'. + // (18,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("int", "Extensions.Add(S, T, T)").WithLocation(18, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(18, 13)); } [Fact] @@ -5926,18 +5892,13 @@ class Program static void Main() { C c = []; + c.Report(); c = [1, 2]; + c.Report(); } } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (14,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int, int)'. - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "C.Add(int, int)").WithLocation(14, 13), - // (14,13): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(14, 13)); + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [1, 2], "); } [Fact] @@ -5984,18 +5945,13 @@ class Program static void Main() { C c = []; + c.Report(); c = [1, 2]; + c.Report(); } } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (14,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int, params int[])'. - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("object", "C.Add(int, params int[])").WithLocation(14, 13), - // (14,13): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // c = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2]").WithArguments("1", "object", "int").WithLocation(14, 13)); + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [1, 2], "); } [Fact] @@ -6112,18 +6068,12 @@ class Program """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,40): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'S.Add(T)'. - // static S Create(T t, U u) => [t, u]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[t, u]").WithArguments("object", "S.Add(T)").WithLocation(7, 40), - // (7,40): error CS1503: Argument 1: cannot convert from 'object' to 'T' - // static S Create(T t, U u) => [t, u]; - Diagnostic(ErrorCode.ERR_BadArgType, "[t, u]").WithArguments("1", "object", "T").WithLocation(7, 40), - // (11,46): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'S.Add(T)'. + // (11,50): error CS1950: The best overloaded Add method 'S.Add(T)' for the collection initializer has some invalid arguments // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, y]").WithArguments("object", "S.Add(T)").WithLocation(11, 46), - // (11,46): error CS1503: Argument 1: cannot convert from 'object' to 'T' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("S.Add(T)").WithLocation(11, 50), + // (11,50): error CS1503: Argument 1: cannot convert from 'U' to 'T' // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_BadArgType, "[x, y]").WithArguments("1", "object", "T").WithLocation(11, 46)); + Diagnostic(ErrorCode.ERR_BadArgType, "y").WithArguments("1", "U", "T").WithLocation(11, 50)); } [Fact] @@ -6179,12 +6129,6 @@ class Program // (9,41): error CS0029: Cannot implicitly convert type 'T' to 'U' // static S Create(T t, U u) => [t, u]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "t").WithArguments("T", "U").WithLocation(9, 41), - // (13,46): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'U'. The best overloaded method is 'S.Add(T)'. - // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, y]").WithArguments("U", "S.Add(T)").WithLocation(13, 46), - // (13,46): error CS1503: Argument 1: cannot convert from 'U' to 'T' - // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_BadArgType, "[x, y]").WithArguments("1", "U", "T").WithLocation(13, 46), // (13,47): error CS0029: Cannot implicitly convert type 'T' to 'U' // static S Create(T x, U y) => [x, y]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("T", "U").WithLocation(13, 47)); @@ -6245,9 +6189,9 @@ static void Main() // (7,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = ['a']; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(7, 13), - // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(7, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(7, 13)); } [Fact] @@ -6425,9 +6369,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (16,31): error CS0122: 'MyCollection.Add(int)' is inaccessible due to its protection level + // (16,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_BadAccess, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(16, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(16, 31)); } [Fact] @@ -6463,9 +6407,9 @@ static void Main() """; comp = CreateCompilation(sourceB, references: new[] { refA }); comp.VerifyEmitDiagnostics( - // (6,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // (6,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, ..x]").WithArguments("MyCollection", "Add").WithLocation(6, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(6, 31)); } [Fact] @@ -6524,9 +6468,9 @@ static void Main() // (13,42): error CS1954: The best overloaded method match 'MyCollection.Add(out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyCollection.Add(out object)").WithLocation(13, 42), - // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(out object)").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -6556,9 +6500,9 @@ static void Main() // (13,42): error CS1954: The best overloaded method match 'MyCollection.Add(ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyCollection.Add(ref object)").WithLocation(13, 42), - // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(ref object)").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -6695,9 +6639,9 @@ static void Main() // (16,42): error CS0411: The type arguments for method 'Extensions.Add(ref MyCollection, out T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "1").WithArguments("Extensions.Add(ref MyCollection, out T)").WithLocation(16, 42), - // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, out object)").WithLocation(18, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); } [Fact] @@ -6730,9 +6674,9 @@ static void Main() // (16,42): error CS0411: The type arguments for method 'Extensions.Add(ref MyCollection, ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "1").WithArguments("Extensions.Add(ref MyCollection, ref T)").WithLocation(16, 42), - // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, ref object)").WithLocation(18, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); } [Fact] @@ -6837,12 +6781,12 @@ static void Main() // (20,21): error CS1503: Argument 2: cannot convert from 'int' to 'string' // y = new() { 3 }; Diagnostic(ErrorCode.ERR_BadArgType, "3").WithArguments("2", "int", "string").WithLocation(20, 21), - // (21,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'int'. The best overloaded method is 'Extensions.Add(ref MyCollection, string)'. + // (21,14): error CS1950: The best overloaded Add method 'Extensions.Add(ref MyCollection, string)' for the collection initializer has some invalid arguments // y = [4]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[4]").WithArguments("int", "Extensions.Add(ref MyCollection, string)").WithLocation(21, 13), - // (21,13): error CS1503: Argument 2: cannot convert from 'int' to 'string' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "4").WithArguments("Extensions.Add(ref MyCollection, string)").WithLocation(21, 14), + // (21,14): error CS1503: Argument 2: cannot convert from 'int' to 'string' // y = [4]; - Diagnostic(ErrorCode.ERR_BadArgType, "[4]").WithArguments("2", "int", "string").WithLocation(21, 13)); + Diagnostic(ErrorCode.ERR_BadArgType, "4").WithArguments("2", "int", "string").WithLocation(21, 14)); } [Fact] @@ -6878,15 +6822,15 @@ static void Main() // (17,21): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // x = new() { "1" }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, @"""1""").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(17, 21), - // (18,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (18,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // x = ["2"]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, @"[""2""]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(18, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[""2""]").WithArguments("MyCollection").WithLocation(18, 13), // (20,21): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // y = new() { 3 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "3").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(20, 21), - // (21,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // (21,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // y = [4]; - Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[4]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(21, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[4]").WithArguments("MyCollection").WithLocation(21, 13)); } [Fact] @@ -6912,9 +6856,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (14,31): error CS1921: The best overloaded method match for 'MyCollection.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // (14,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(14, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(14, 31)); } [Fact] @@ -8040,15 +7984,18 @@ static void Main() comp = CreateCompilation(new[] { sourceC, s_collectionExtensions }, references: new[] { refB }); comp.VerifyEmitDiagnostics( - // 0.cs(6,13): error CS0012: The type 'A1' is defined in an assembly that is not referenced. You must add a reference to assembly 'a897d975-a839-4fff-828b-deccf9495adc, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // 0.cs(6,13): error CS0012: The type 'A1' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // x = []; Diagnostic(ErrorCode.ERR_NoTypeDef, "[]").WithArguments("A1", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(6, 13), - // 0.cs(8,13): error CS0012: The type 'A1' is defined in an assembly that is not referenced. You must add a reference to assembly 'a897d975-a839-4fff-828b-deccf9495adc, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // 0.cs(8,13): error CS0012: The type 'A1' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // x = [1, 2]; Diagnostic(ErrorCode.ERR_NoTypeDef, "[1, 2]").WithArguments("A1", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 13), - // 0.cs(13,13): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly 'a897d975-a839-4fff-828b-deccf9495adc, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // 0.cs(13,14): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // y = [3, 4]; - Diagnostic(ErrorCode.ERR_NoTypeDef, "[3, 4]").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 13)); + Diagnostic(ErrorCode.ERR_NoTypeDef, "3").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 14), + // 0.cs(13,17): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // y = [3, 4]; + Diagnostic(ErrorCode.ERR_NoTypeDef, "4").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 17)); } [Fact] @@ -8147,12 +8094,12 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'KeyValuePair'. The best overloaded method is 'Dictionary.Add(int, int)'. + // (7,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[default]").WithArguments("System.Collections.Generic.KeyValuePair", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(7, 13), - // (8,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'KeyValuePair'. The best overloaded method is 'Dictionary.Add(int, int)'. + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(7, 13), + // (8,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [new KeyValuePair(1, 2)]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.KeyValuePair", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(8, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(8, 13), // (9,15): error CS1003: Syntax error, ',' expected // d = [3:4]; Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",").WithLocation(9, 15), @@ -9433,18 +9380,42 @@ static void Main() if (targetElementType == "int") { comp.VerifyEmitDiagnostics( - // 1.cs(10,26): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection.Add(int)'. + // 1.cs(10,27): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgType, "..d1").WithArguments("1", "object", "int").WithLocation(10, 27), + // 1.cs(10,29): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "d1").WithArguments("MyCollection.Add(int)").WithLocation(10, 29), + // 1.cs(10,33): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgType, "..d2").WithArguments("1", "object", "int").WithLocation(10, 33), + // 1.cs(10,35): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments // MyCollection c = [..d1, ..d2, ..e1, ..e2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..d1, ..d2, ..e1, ..e2]").WithArguments("object", "MyCollection.Add(int)").WithLocation(10, 26), - // 1.cs(10,26): error CS1503: Argument 1: cannot convert from 'object' to 'int' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "d2").WithArguments("MyCollection.Add(int)").WithLocation(10, 35), + // 1.cs(10,39): error CS1503: Argument 1: cannot convert from 'object' to 'int' // MyCollection c = [..d1, ..d2, ..e1, ..e2]; - Diagnostic(ErrorCode.ERR_BadArgType, "[..d1, ..d2, ..e1, ..e2]").WithArguments("1", "object", "int").WithLocation(10, 26), - // 1.cs(14,13): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection.Add(int)'. + Diagnostic(ErrorCode.ERR_BadArgType, "..e1").WithArguments("1", "object", "int").WithLocation(10, 39), + // 1.cs(10,41): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "e1").WithArguments("MyCollection.Add(int)").WithLocation(10, 41), + // 1.cs(10,45): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgType, "..e2").WithArguments("1", "object", "int").WithLocation(10, 45), + // 1.cs(10,47): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments + // MyCollection c = [..d1, ..d2, ..e1, ..e2]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "e2").WithArguments("MyCollection.Add(int)").WithLocation(10, 47), + // 1.cs(14,14): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // c = [..(dynamic)x, ..(IEnumerable)y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..(dynamic)x").WithArguments("1", "object", "int").WithLocation(14, 14), + // 1.cs(14,16): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments // c = [..(dynamic)x, ..(IEnumerable)y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..(dynamic)x, ..(IEnumerable)y]").WithArguments("object", "MyCollection.Add(int)").WithLocation(14, 13), - // 1.cs(14,13): error CS1503: Argument 1: cannot convert from 'object' to 'int' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "(dynamic)x").WithArguments("MyCollection.Add(int)").WithLocation(14, 16), + // 1.cs(14,28): error CS1503: Argument 1: cannot convert from 'object' to 'int' // c = [..(dynamic)x, ..(IEnumerable)y]; - Diagnostic(ErrorCode.ERR_BadArgType, "[..(dynamic)x, ..(IEnumerable)y]").WithArguments("1", "object", "int").WithLocation(14, 13)); + Diagnostic(ErrorCode.ERR_BadArgType, "..(IEnumerable)y").WithArguments("1", "object", "int").WithLocation(14, 28), + // 1.cs(14,30): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments + // c = [..(dynamic)x, ..(IEnumerable)y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "(IEnumerable)y").WithArguments("MyCollection.Add(int)").WithLocation(14, 30)); } else { @@ -15071,9 +15042,9 @@ static void Main() // (6,24): error CS0416: 'T': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(T), "ToString")] Diagnostic(ErrorCode.ERR_AttrArgWithTypeVars, "typeof(T)").WithArguments("T").WithLocation(6, 24), - // (19,44): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) + // (19,44): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [null]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("Container.MyCollection", "Add").WithLocation(19, 44), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("Container.MyCollection").WithLocation(19, 44), // (19,45): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // Container.MyCollection y = [null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(19, 45)); @@ -15584,9 +15555,9 @@ static void Main() // (7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] Diagnostic(ErrorCode.ERR_AttrArgWithTypeVars, "typeof(MyCollectionBuilder)").WithArguments("Container.MyCollectionBuilder").WithLocation(7, 24), - // (27,41): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) + // (27,41): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [default]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("Container.MyCollection", "Add").WithLocation(27, 41)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("Container.MyCollection").WithLocation(27, 41)); } [CombinatorialData] @@ -16366,9 +16337,9 @@ static void Main() """; comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // (6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [2]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[2]").WithArguments("MyCollection", "Add").WithLocation(6, 26)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[2]").WithArguments("MyCollection").WithLocation(6, 26)); } [CombinatorialData] @@ -16484,9 +16455,9 @@ static void Main() // 1.cs(6,26): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection y = [1, 2, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1, 2, 3]").WithLocation(6, 26), - // 1.cs(6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // 1.cs(6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, 3]").WithArguments("MyCollection", "Add").WithLocation(6, 26)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, 3]").WithArguments("MyCollection").WithLocation(6, 26)); } [Fact] @@ -16555,9 +16526,9 @@ static void Main() // 1.cs(6,34): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection y = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1, 2, null]").WithLocation(6, 34), - // 1.cs(6,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // 1.cs(6,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, null]; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, null]").WithArguments("MyCollection", "Add").WithLocation(6, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, null]").WithArguments("MyCollection").WithLocation(6, 34)); } [Fact] @@ -25110,11 +25081,11 @@ .. GetConfig(), var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (4,52): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'KeyValuePair'. The best overloaded method is 'Dictionary.Add(string, object)'. + // (4,52): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // Dictionary Config => /**/[ - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[ + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[ .. GetConfig(), - ]").WithArguments("System.Collections.Generic.KeyValuePair", "System.Collections.Generic.Dictionary.Add(string, object)").WithLocation(4, 52)); + ]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(4, 52)); VerifyOperationTreeForTest(comp, """ @@ -25985,13 +25956,7 @@ public static void M(int[] i) { } var comp = CreateCompilation(source).VerifyEmitDiagnostics( // (3,7): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // C x = [1]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1]").WithLocation(3, 7), - // (3,7): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int)'. - // C x = [1]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("object", "C.Add(int)").WithLocation(3, 7), - // (3,7): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // C x = [1]; // 1 - Diagnostic(ErrorCode.ERR_BadArgType, "[1]").WithArguments("1", "object", "int").WithLocation(3, 7) + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1]").WithLocation(3, 7) ); var tree = comp.SyntaxTrees.First(); @@ -26034,13 +25999,7 @@ public static void M(int[] i) { } var comp = CreateCompilation(source).VerifyEmitDiagnostics( // (4,7): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // C x = [..values]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[..values]").WithLocation(4, 7), - // (4,7): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'C.Add(int)'. - // C x = [..values]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..values]").WithArguments("object", "C.Add(int)").WithLocation(4, 7), - // (4,7): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // C x = [..values]; // 1 - Diagnostic(ErrorCode.ERR_BadArgType, "[..values]").WithArguments("1", "object", "int").WithLocation(4, 7) + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[..values]").WithLocation(4, 7) ); var tree = comp.SyntaxTrees.First(); @@ -26081,12 +26040,6 @@ public void Add(int i) { } // (4,7): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // C x = [1]; // 1 Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1]").WithLocation(4, 7), - // (4,7): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'string'. The best overloaded method is 'C.Add(int)'. - // C x = [1]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("string", "C.Add(int)").WithLocation(4, 7), - // (4,7): error CS1503: Argument 1: cannot convert from 'string' to 'int' - // C x = [1]; // 1 - Diagnostic(ErrorCode.ERR_BadArgType, "[1]").WithArguments("1", "string", "int").WithLocation(4, 7), // (4,8): error CS0029: Cannot implicitly convert type 'int' to 'string' // C x = [1]; // 1 Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "string").WithLocation(4, 8) @@ -26126,12 +26079,6 @@ public static void M(int[] i) { } // (5,7): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // C x = [..values]; // 1 Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[..values]").WithLocation(5, 7), - // (5,7): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'string'. The best overloaded method is 'C.Add(int)'. - // C x = [..values]; // 1 - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..values]").WithArguments("string", "C.Add(int)").WithLocation(5, 7), - // (5,7): error CS1503: Argument 1: cannot convert from 'string' to 'int' - // C x = [..values]; // 1 - Diagnostic(ErrorCode.ERR_BadArgType, "[..values]").WithArguments("1", "string", "int").WithLocation(5, 7), // (5,10): error CS0029: Cannot implicitly convert type 'int' to 'string' // C x = [..values]; // 1 Diagnostic(ErrorCode.ERR_NoImplicitConv, "values").WithArguments("int", "string").WithLocation(5, 10) @@ -26824,20 +26771,11 @@ class MyCollection2 : IEnumerable where TAdd : TElemen } """; - var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics( - // 0.cs(4,24): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection1.Add(int)'. - // MyCollection1 x = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2, 3]").WithArguments("object", "MyCollection1.Add(int)").WithLocation(4, 24), - // 0.cs(4,24): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // MyCollection1 x = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2, 3]").WithArguments("1", "object", "int").WithLocation(4, 24), - // 0.cs(6,32): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection2.Add(int)'. - // MyCollection2 y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2, 3]").WithArguments("object", "MyCollection2.Add(int)").WithLocation(6, 32), - // 0.cs(6,32): error CS1503: Argument 1: cannot convert from 'object' to 'int' - // MyCollection2 y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2, 3]").WithArguments("1", "object", "int").WithLocation(6, 32)); + CompileAndVerify( + new[] { source, s_collectionExtensions }, + targetFramework: TargetFramework.Net70, + verify: Verification.FailsPEVerify, + expectedOutput: IncludeExpectedOutput("[1, 2, 3], [1, 2, 3], ")); } [Fact] @@ -26860,19 +26798,19 @@ class MyCollection2 : IEnumerable where TAdd : TElemen var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (4,32): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'MyCollection2.Add(int)'. + // (4,33): error CS1950: The best overloaded Add method 'MyCollection2.Add(int)' for the collection initializer has some invalid arguments // MyCollection2 y = [new object()]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[new object()]").WithArguments("object", "MyCollection2.Add(int)").WithLocation(4, 32), - // (4,32): error CS1503: Argument 1: cannot convert from 'object' to 'int' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "new object()").WithArguments("MyCollection2.Add(int)").WithLocation(4, 33), + // (4,33): error CS1503: Argument 1: cannot convert from 'object' to 'int' // MyCollection2 y = [new object()]; - Diagnostic(ErrorCode.ERR_BadArgType, "[new object()]").WithArguments("1", "object", "int").WithLocation(4, 32) + Diagnostic(ErrorCode.ERR_BadArgType, "new object()").WithArguments("1", "object", "int").WithLocation(4, 33) ); } [Fact] public void GenericIEnumerable_DifferentConversionToAdd() { - // For purpose of conversion, we rely on conversion from numeric literal to uint (from IEnumerable) + // For purpose of conversion, we rely the existence of an Add method. // But for purpose of construction, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) string source = """ using System.Collections; @@ -26890,21 +26828,18 @@ class MyCollection : IEnumerable } """; - var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics( - // 0.cs(4,18): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'uint'. The best overloaded method is 'MyCollection.Add(sbyte)'. - // MyCollection x = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2, 3]").WithArguments("uint", "MyCollection.Add(sbyte)").WithLocation(4, 18), - // 0.cs(4,18): error CS1503: Argument 1: cannot convert from 'uint' to 'sbyte' - // MyCollection x = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2, 3]").WithArguments("1", "uint", "sbyte").WithLocation(4, 18)); + CompileAndVerify( + new[] { source, s_collectionExtensions }, + targetFramework: TargetFramework.Net70, + verify: Verification.FailsPEVerify, + expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); } [Fact] public void GenericIEnumerable_NoConversionToAdd() { - // For purpose of conversion, we rely on conversion from numeric literal to uint (from IEnumerable) - // But for purpose of construction, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) + // For purpose of conversion, we rely the existence of an Add method. + // But for purpose of construction, there is no conversion from uint to sbyte (from Add(sbyte)) string source = """ using System.Collections; using System.Collections.Generic; @@ -26922,12 +26857,12 @@ class MyCollection : IEnumerable var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(4,18): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'uint'. The best overloaded method is 'MyCollection.Add(sbyte)'. + // 0.cs(4,19): error CS1950: The best overloaded Add method 'MyCollection.Add(sbyte)' for the collection initializer has some invalid arguments // MyCollection x = [uint.MaxValue]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[uint.MaxValue]").WithArguments("uint", "MyCollection.Add(sbyte)").WithLocation(4, 18), - // 0.cs(4,18): error CS1503: Argument 1: cannot convert from 'uint' to 'sbyte' + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "uint.MaxValue").WithArguments("MyCollection.Add(sbyte)").WithLocation(4, 19), + // 0.cs(4,19): error CS1503: Argument 1: cannot convert from 'uint' to 'sbyte' // MyCollection x = [uint.MaxValue]; - Diagnostic(ErrorCode.ERR_BadArgType, "[uint.MaxValue]").WithArguments("1", "uint", "sbyte").WithLocation(4, 18) + Diagnostic(ErrorCode.ERR_BadArgType, "uint.MaxValue").WithArguments("1", "uint", "sbyte").WithLocation(4, 19) ); } @@ -27144,12 +27079,9 @@ class Collection : IEnumerable """; CreateCompilation(source).VerifyEmitDiagnostics( - // (4,16): error CS9215: Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type 'object'. The best overloaded method is 'Collection.Add(I1)'. - // Collection c = [new C()]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[new C()]").WithArguments("object", "Collection.Add(I1)").WithLocation(4, 16), - // (4,16): error CS1503: Argument 1: cannot convert from 'object' to 'I1' + // (4,17): error CS0121: The call is ambiguous between the following methods or properties: 'Collection.Add(I1)' and 'Collection.Add(I2)' // Collection c = [new C()]; - Diagnostic(ErrorCode.ERR_BadArgType, "[new C()]").WithArguments("1", "object", "I1").WithLocation(4, 16)); + Diagnostic(ErrorCode.ERR_AmbigCall, "new C()").WithArguments("Collection.Add(I1)", "Collection.Add(I2)").WithLocation(4, 17)); } [Fact] @@ -34296,6 +34228,2001 @@ static void Main() """); } + [Fact] + public void AddMethod_System_Windows_Input_InputGestureCollection() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + namespace System.Windows.Input + { + public class InputGesture + { + } + public sealed class InputGestureCollection : IList + { + private readonly List _list = new(); + object IList.this[int index] { get => _list[index]; set => _list[index] = value; } + bool IList.IsFixedSize => false; + bool IList.IsReadOnly => false; + int ICollection.Count => _list.Count; + bool ICollection.IsSynchronized => false; + object ICollection.SyncRoot => this; + int IList.Add(object value) => ((IList)_list).Add(value); + void IList.Clear() { _list.Clear(); } + bool IList.Contains(object value) => _list.Contains(value); + void ICollection.CopyTo(Array array, int index) => ((IList)_list).CopyTo(array, index); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + int IList.IndexOf(object value) => _list.IndexOf(value); + void IList.Insert(int index, object value) => _list.Insert(index, value); + void IList.Remove(object value) => _list.Remove(value); + void IList.RemoveAt(int index) => _list.RemoveAt(index); + public int Add(InputGesture value) => ((IList)_list).Add(value); + } + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using System.Windows.Input; + class Program + { + static void Main() + { + InputGestureCollection c = [new InputGesture(), null]; + c.Report(); + } + } + """; + CompileAndVerify([sourceB, s_collectionExtensions], references: [refA], expectedOutput: "[System.Windows.Input.InputGesture, null], "); + } + + [Fact] + public void AddMethod_System_CommandLine_Command() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + namespace System.CommandLine + { + public class Symbol + { + } + public class Argument : Symbol + { + } + public class Command : Symbol, IEnumerable + { + private readonly List _symbols = new(); + public IEnumerator GetEnumerator() => _symbols.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public void Add(Argument argument) { _symbols.Add(argument); } + public void Add(Command command) { _symbols.Add(command); } + } + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using System.CommandLine; + class Program + { + static void Main() + { + Command c = [new Argument(), new Command()]; + c.Report(); + } + } + """; + CompileAndVerify([sourceB, s_collectionExtensions], references: [refA], expectedOutput: "[System.CommandLine.Argument, []], "); + } + + [Fact] + public void AddMethod_Accessibility() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + partial class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + private void Add(int i) { _list.Add(i is T t ? t : default); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB1]); + comp.VerifyEmitDiagnostics( + // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + + string sourceB2 = """ + partial class MyCollection + { + public static void Run() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + class Program + { + static void Main() + { + MyCollection.Run(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Extension_Accessibility() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + internal void __AddInternal(int i) { _list.Add(i is T t ? t : default); } + } + internal static class Extensions + { + public static void Add(this MyCollection c, int i) { c.__AddInternal(i); } + } + """; + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + var comp = CreateCompilation(sourceA); + var refA = comp.ToMetadataReference(); + + comp = CreateCompilation([sourceB, s_collectionExtensions], references: [refA]); + comp.VerifyEmitDiagnostics( + // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + } + + [Fact] + public void AddMethod_Overloads() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public void Add(string s) { _list.Add(s is T t ? t : default); } + public void Add(int i) { _list.Add(i is T t ? t : default); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + string x = "1"; + string[] y = ["2", "3"]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB3 = """ + class Program + { + static void Main() + { + int? x = 1; + int?[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB3]); + comp.VerifyEmitDiagnostics( + // (7,33): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(string)").WithLocation(7, 33), + // (7,33): error CS1503: Argument 1: cannot convert from 'int?' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "int?", "string").WithLocation(7, 33), + // (7,36): error CS1503: Argument 1: cannot convert from 'int?' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "int?", "string").WithLocation(7, 36), + // (7,38): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(string)").WithLocation(7, 38)); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_01(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add({{refKind}} T t) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("out")] + [InlineData("ref")] + public void AddMethod_ByRef_02(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add({{refKind}} T t) { t = default; _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_03(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + interface IA { } + interface IB { } + interface IC { } + class C : IA, IB, IC + { + private readonly int _i; + public C(int i) { _i = i; } + public override string ToString() => _i.ToString(); + public static implicit operator C(int i) => new(i); + } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(out IA a) => throw null; + public void Add(ref IB b) => throw null; + public void Add({{refKind}} IC c) { _list.Add(c); } + } + class Program + { + static void Main() + { + C x = 1; + C[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_Extension_01(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("out")] + [InlineData("ref")] + public void AddMethod_ByRef_Extension_02(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} T t) { t = default; collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_Extension_03(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + ref struct R { } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + public void Add(R r) => throw null; + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("out")] + [InlineData("ref")] + public void AddMethod_ByRef_Extension_04(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + ref struct R { } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + public void Add(R r) => throw null; + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} T t) { t = default; collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (21,33): error CS1950: The best overloaded Add method 'MyCollection.Add(R)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(R)").WithLocation(21, 33), + // (21,33): error CS1503: Argument 1: cannot convert from 'int' to 'R' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "int", "R").WithLocation(21, 33), + // (21,36): error CS1503: Argument 1: cannot convert from 'int' to 'R' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "int", "R").WithLocation(21, 36), + // (21,38): error CS1950: The best overloaded Add method 'MyCollection.Add(R)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(R)").WithLocation(21, 38), + // (21,41): error CS1950: The best overloaded Add method 'MyCollection.Add(R)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "null").WithArguments("MyCollection.Add(R)").WithLocation(21, 41), + // (21,41): error CS1503: Argument 1: cannot convert from '' to 'R' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "", "R").WithLocation(21, 41)); + } + + [Theory] + [InlineData("out")] + [InlineData("ref")] + public void AddMethod_ByRef_Extension_05(string refKind) + { + string source = $$""" + using N; + using System.Collections; + using System.Collections.Generic; + ref struct R { } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + public void Add(R r) => throw null; + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} T t) { t = default; collection.__AddInternal(t); } + } + namespace N + { + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_Extension_06(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + interface IA { } + interface IB { } + interface IC { } + class C : IA, IB, IC + { + private readonly int _i; + public C(int i) { _i = i; } + public override string ToString() => _i.ToString(); + public static implicit operator C(int i) => new(i); + } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(out IA a) => throw null; + public void Add(ref IB b) => throw null; + internal void __AddInternal(IC c) { _list.Add(c); } + } + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} IC c) { collection.__AddInternal(c); } + } + class Program + { + static void Main() + { + C x = 1; + C[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_ByRef_Extension_07(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + using N; + interface IA { } + interface IB { } + interface IC { } + class C : IA, IB, IC + { + private readonly int _i; + public C(int i) { _i = i; } + public override string ToString() => _i.ToString(); + public static implicit operator C(int i) => new(i); + } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(IC c) { _list.Add(c); } + } + static class Extensions + { + public static void Add(this MyCollection collection, out IA a) => throw null; + public static void Add(this MyCollection collection, ref IB b) => throw null; + } + namespace N + { + static class Extensions + { + public static void Add(this MyCollection collection, {{refKind}} IC c) { collection.__AddInternal(c); } + } + } + class Program + { + static void Main() + { + C x = 1; + C[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Fact] + public void AddMethod_01() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add() { _list.Add(default); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + } + + [Fact] + public void AddMethod_02() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t, int x = 1, int y = 2) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Fact] + public void AddMethod_03() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t, int x, int y = 2) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + } + + [Fact] + public void AddMethod_04() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(params T[] args) + { + if (args is null) return; + _list.AddRange(args); + } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + MyCollection x = new() { (int?)null, null }; + MyCollection y = [(int?)null, null]; + x.Report(); + y.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[null], [null], "); + } + + [Fact] + public void AddMethod_05() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T x, params T[] y) { _list.Add(x); _list.AddRange(y); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Fact] + public void AddMethod_06() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(string s) { } + internal void __AddInternal(T t) { _list.Add(t); } + } + namespace N + { + internal static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using N; + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceB, sourceA, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + comp = CreateCompilation([sourceB, s_collectionExtensions], references: [refA]); + comp.VerifyEmitDiagnostics( + // (8,32): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(string)").WithLocation(8, 32), + // (8,32): error CS1503: Argument 1: cannot convert from 'int' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "int", "string").WithLocation(8, 32), + // (8,35): error CS1503: Argument 1: cannot convert from 'int' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "int", "string").WithLocation(8, 35), + // (8,37): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(string)").WithLocation(8, 37)); + } + + [Fact] + public void AddMethod_07() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(string s) => throw null; + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, int i) { collection.__AddInternal(i); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceB1, sourceA, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + object x = 1; + object[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceB2, sourceA]); + comp.VerifyEmitDiagnostics( + // (7,35): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(string)").WithLocation(7, 35), + // (7,35): error CS1503: Argument 1: cannot convert from 'object' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "object", "string").WithLocation(7, 35), + // (7,38): error CS1503: Argument 1: cannot convert from 'object' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "object", "string").WithLocation(7, 38), + // (7,40): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(string)").WithLocation(7, 40)); + } + + [Fact] + public void AddMethod_Extension_01() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection) { collection.__AddInternal(default); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + + [Fact] + public void AddMethod_Extension_02() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t, int x = 1, int y = 2) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Fact] + public void AddMethod_Extension_03() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t, int x, int y = 2) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + + [Fact] + public void AddMethod_Extension_04() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, params T[] args) + { + if (args is null) return; + foreach (var a in args) + collection.__AddInternal(a); + } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + MyCollection x = new() { (int?)null, null }; + MyCollection y = [(int?)null, null]; + x.Report(); + y.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[null], [null], "); + } + + [Fact] + public void AddMethod_Extension_05() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T x, params T[] y) + { + collection.__AddInternal(x); + foreach (var a in y) + collection.__AddInternal(a); + } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); + } + + [Fact] + public void AddMethod_Extension_06() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + public static class Extensions + { + public static void Add(this MyCollection collection, string s) { } + } + namespace N + { + internal static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using N; + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceB, sourceA, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + comp = CreateCompilation([sourceB, s_collectionExtensions], references: [refA]); + comp.VerifyEmitDiagnostics( + // (8,32): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(8, 32), + // (8,32): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("2", "int", "string").WithLocation(8, 32), + // (8,35): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("2", "int", "string").WithLocation(8, 35), + // (8,37): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(8, 37)); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref")] + [InlineData("ref readonly")] + public void AddMethod_Extension_07(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + private List _list; + IEnumerator IEnumerable.GetEnumerator() => GetList().GetEnumerator(); + internal void __AddInternal(T t) { GetList().Add(t); } + private List GetList() => _list ??= new(); + } + static class Extensions + { + public static void Add(this {{refKind}} MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + string expectedOutput = (refKind == "ref") ? "[1, 2, 3], " : "[], "; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: expectedOutput); + } + + [Fact] + public void AddMethod_Base() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + protected abstract void __AddInternal(T t); + public void Add(T t) => __AddInternal(t); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + protected override void __AddInternal(T t) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Derived() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + protected void __AddInternal(T t) { _list.Add(t); } + } + class MyCollectionDerived : MyCollection + { + public void Add(T t) => __AddInternal(t); + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollectionDerived z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Theory] + [InlineData("class")] + [InlineData("struct")] + public void AddMethod_ExplicitImplementation(string structOrClass) + { + string sourceA = $$""" + using System.Collections; + using System.Collections.Generic; + interface IAdd + { + void Add(T t); + } + {{structOrClass}} MyCollection : IAdd, IEnumerable + { + private List _list; + IEnumerator IEnumerable.GetEnumerator() => GetList().GetEnumerator(); + void IAdd.Add(T t) { GetList().Add(t); } + private List GetList() => _list ??= new(); + } + """; + string sourceB = """ + class Program + { + static void Main() + { + object x = 1; + object[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + string sourceC = $$""" + static class Extensions + { + public static void Add(this {{(structOrClass == "struct" ? "ref" : "")}} T collection, U u) + where T : {{structOrClass}}, IAdd + { + collection.Add(u); + } + } + """; + + var comp = CreateCompilation([sourceA, sourceB, s_collectionExtensions]); + comp.VerifyEmitDiagnostics( + // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + + CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Static() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public static void Add(T t) => throw null; + internal void __AddInternal(T t) { _list.Add(t); } + } + """; + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + string sourceC = """ + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + """; + + var comp = CreateCompilation([sourceA, sourceB, s_collectionExtensions]); + comp.VerifyEmitDiagnostics( + // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + + CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Generic_01() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(U u) { _list.Add(u is T t ? t : default); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + MyCollection z = [null]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB2]); + comp.VerifyEmitDiagnostics( + // (5,35): error CS0411: The type arguments for method 'MyCollection.Add(U)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "null").WithArguments("MyCollection.Add(U)").WithLocation(5, 35)); + } + + [Fact] + public void AddMethod_Generic_02() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); + } + + [Fact] + public void AddMethod_Generic_03() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t, U u = default) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); + } + + [Fact] + public void AddMethod_Generic_04() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, U u) { collection.__AddInternal(u is T t ? t : default); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + MyCollection z = [null]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB2]); + comp.VerifyEmitDiagnostics( + // (5,35): error CS0411: The type arguments for method 'Extensions.Add(MyCollection, U)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "null").WithArguments("Extensions.Add(MyCollection, U)").WithLocation(5, 35)); + } + + [Fact] + public void AddMethod_Generic_05() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 34)); + } + + [Fact] + public void AddMethod_Generic_06() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + MyCollection z = [null]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB2]); + comp.VerifyEmitDiagnostics( + // (5,35): error CS0411: The type arguments for method 'Extensions.Add(MyCollection, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "null").WithArguments("Extensions.Add(MyCollection, T)").WithLocation(5, 35)); + } + + [Fact] + public void AddMethod_Generic_07() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T x, U y = default, T z = default) { collection.__AddInternal(x is U u ? u : default); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Generic_08() + { + string sourceA = """ + using System; + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(Func f) { _list.Add(f); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB1]); + comp.VerifyEmitDiagnostics( + // (7,35): error CS0411: The type arguments for method 'MyCollection.Add(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "x").WithArguments("MyCollection.Add(System.Func)").WithLocation(7, 35), + // (7,40): error CS0411: The type arguments for method 'MyCollection.Add(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "y").WithArguments("MyCollection.Add(System.Func)").WithLocation(7, 40), + // (7,43): error CS0411: The type arguments for method 'MyCollection.Add(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "null").WithArguments("MyCollection.Add(System.Func)").WithLocation(7, 43)); + + string sourceB2 = """ + using System; + class Program + { + static void Main() + { + Func x = _ => 1; + Func[] y = [_ => "2"]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[System.Func`2[System.Object,System.Int32], System.Func`2[System.Object,System.String]], "); + } + + [Fact] + public void AddMethod_Generic_09() + { + string sourceA = """ + using System; + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(Delegate d) { _list.Add(d); } + } + static class Extensions + { + public static void Add(this MyCollection collection, Func f) { collection.__AddInternal(f); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB1]); + comp.VerifyEmitDiagnostics( + // (7,35): error CS0411: The type arguments for method 'Extensions.Add(MyCollection, Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "x").WithArguments("Extensions.Add(MyCollection, System.Func)").WithLocation(7, 35), + // (7,40): error CS0411: The type arguments for method 'Extensions.Add(MyCollection, Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "y").WithArguments("Extensions.Add(MyCollection, System.Func)").WithLocation(7, 40), + // (7,43): error CS0411: The type arguments for method 'Extensions.Add(MyCollection, Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "null").WithArguments("Extensions.Add(MyCollection, System.Func)").WithLocation(7, 43)); + + string sourceB2 = """ + using System; + class Program + { + static void Main() + { + Func x = _ => 1; + Func[] y = [_ => "2"]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], expectedOutput: "[System.Func`2[System.Object,System.Int32], System.Func`2[System.Object,System.String]], "); + } + + // [Obsolete] attribute is ignored when checking for Add for conversion. + [Fact] + public void AddMethod_Obsolete_01() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + [Obsolete("do not use", error: true)] + public void Add(string s) => throw null; + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + // [Obsolete] attribute is ignored when checking for Add for conversion. + [Fact] + public void AddMethod_Obsolete_02() + { + string source = """ + using N; + using System; + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + [Obsolete("do not use", error: true)] + public static void Add(this MyCollection collection, string s) => throw null; + } + namespace N + { + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Unsafe() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + unsafe public void Add(void* p) => throw null; + internal void __AddInternal(T t) { _list.Add(t); } + } + """; + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + string sourceC = """ + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + """; + + var comp = CreateCompilation([sourceA, sourceB, s_collectionExtensions], options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (7,35): error CS1950: The best overloaded Add method 'MyCollection.Add(void*)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(void*)").WithLocation(7, 35), + // (7,35): error CS1503: Argument 1: cannot convert from 'int' to 'void*' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "int", "void*").WithLocation(7, 35), + // (7,38): error CS1503: Argument 1: cannot convert from 'int' to 'void*' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "int", "void*").WithLocation(7, 38), + // (7,40): error CS1950: The best overloaded Add method 'MyCollection.Add(void*)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(void*)").WithLocation(7, 40)); + + CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], options: TestOptions.UnsafeReleaseExe, expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_RefStruct_01() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + ref struct R { } + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(R r) => throw null; + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_RefStruct_02() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + ref struct R + { + public R(object value) { Value = value; } + public readonly object Value; + } + class MyCollection : IEnumerable + { + private List _list = new(); + public MyEnumerator GetEnumerator() => new MyEnumerator(_list); + IEnumerator IEnumerable.GetEnumerator() => throw null; + public void Add(object o) => throw null; + internal void __AddInternal(R r) { _list.Add(r.Value); } + } + class MyEnumerator + { + private List _list; + private int _index = -1; + public MyEnumerator(List list) { _list = list; } + public bool MoveNext() + { + if (_index < _list.Count) _index++; + return _index < _list.Count; + } + public R Current => new R(_list[_index]); + } + static class Extensions + { + public static void Add(this MyCollection collection, R r) { collection.__AddInternal(r); } + } + class Program + { + static void Main() + { + MyCollection x = [new R(1)]; + MyCollection y = [..x, new R(2)]; + foreach (var i in y) + Console.Write("{0}, ", i.Value); + } + } + """; + CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: "1, 2, "); + } + + [Fact] + public void AddMethod_UseSiteErrors() + { + string assemblyA = GetUniqueName(); + string sourceA = """ + public class A { } + """; + var comp = CreateCompilation(sourceA, assemblyName: assemblyA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(A a) => throw null; + public void __AddInternal(T t) { _list.Add(t); } + } + """; + comp = CreateCompilation(sourceB, references: [refA]); + var refB = comp.EmitToImageReference(); + + string sourceC = """ + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + + CompileAndVerify([sourceC, s_collectionExtensions], references: [refA, refB], expectedOutput: "[1, 2, 3], "); + + comp = CreateCompilation([sourceC, s_collectionExtensions], references: [refB]); + comp.VerifyEmitDiagnostics( + // (11,35): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly '2537f385-b53e-4fea-834a-b23059cd7f17, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoTypeDef, "x").WithArguments("A", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 35), + // (11,40): error CS0012: The type 'A' is defined in an assembly that is not referenced. You must add a reference to assembly '2537f385-b53e-4fea-834a-b23059cd7f17, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoTypeDef, "y").WithArguments("A", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 40)); + } + [Fact] public void SynthesizedReadOnlyList_SingleElement() { From 88caf1227a9db34003acd4ac6b361ab15d95f088 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:06:12 -0700 Subject: [PATCH 02/18] IOperation --- .../Portable/Binder/Binder_Conversions.cs | 24 +- .../LocalRewriter_CollectionExpression.cs | 4 +- .../Operations/CSharpOperationFactory.cs | 7 +- .../Semantics/CollectionExpressionTests.cs | 398 ++++++++++++++++++ 4 files changed, 422 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 0924b078e972e..0454a409555fb 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1369,16 +1369,28 @@ static bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMe /// return the argument to the collection initializer Add method or null if the element is not a /// collection initializer node. Otherwise, return the element as is. /// - internal static BoundExpression? GetUnderlyingCollectionExpressionElement(BoundCollectionExpression expr, BoundExpression? element) + internal static BoundExpression GetUnderlyingCollectionExpressionElement(BoundCollectionExpression expr, BoundExpression element, bool throwOnErrors) { if (expr.CollectionTypeKind is CollectionExpressionTypeKind.ImplementsIEnumerable) { - return element switch + switch (element) { - BoundCollectionElementInitializer collectionInitializer => getCollectionInitializerElement(collectionInitializer), - BoundDynamicCollectionElementInitializer dynamicInitializer => dynamicInitializer.Arguments[0], - _ => null, - }; + case BoundCollectionElementInitializer collectionInitializer: + return getCollectionInitializerElement(collectionInitializer); + case BoundDynamicCollectionElementInitializer dynamicInitializer: + return dynamicInitializer.Arguments[0]; + } + if (throwOnErrors) + { + throw ExceptionUtilities.UnexpectedValue(element); + } + switch (element) + { + case BoundCall call: + return call.Arguments[call.InvokedAsExtensionMethod ? 1 : 0]; + default: + return element; + } } return element; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index ca0c4e3354ab1..ef6e145345c23 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -118,7 +118,7 @@ static BoundNode unwrapListElement(BoundCollectionExpression node, BoundNode ele if (element is BoundCollectionExpressionSpreadElement spreadElement) { Debug.Assert(spreadElement.IteratorBody is { }); - var iteratorBody = Binder.GetUnderlyingCollectionExpressionElement(node, ((BoundExpressionStatement)spreadElement.IteratorBody).Expression); + var iteratorBody = Binder.GetUnderlyingCollectionExpressionElement(node, ((BoundExpressionStatement)spreadElement.IteratorBody).Expression, throwOnErrors: true); Debug.Assert(iteratorBody is { }); return spreadElement.Update( spreadElement.Expression, @@ -131,7 +131,7 @@ static BoundNode unwrapListElement(BoundCollectionExpression node, BoundNode ele } else { - var result = Binder.GetUnderlyingCollectionExpressionElement(node, (BoundExpression)element); + var result = Binder.GetUnderlyingCollectionExpressionElement(node, (BoundExpression)element, throwOnErrors: true); Debug.Assert(result is { }); return result; } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 9a43c65d82474..acf8246550b90 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1257,13 +1257,14 @@ private IOperation CreateBoundCollectionExpressionElement(BoundCollectionExpress { return element is BoundCollectionExpressionSpreadElement spreadElement ? CreateBoundCollectionExpressionSpreadElement(expr, spreadElement) : - Create(Binder.GetUnderlyingCollectionExpressionElement(expr, (BoundExpression)element) ?? element); + Create(Binder.GetUnderlyingCollectionExpressionElement(expr, (BoundExpression)element, throwOnErrors: false)); } private ISpreadOperation CreateBoundCollectionExpressionSpreadElement(BoundCollectionExpression expr, BoundCollectionExpressionSpreadElement element) { - var iteratorBody = ((BoundExpressionStatement?)element.IteratorBody)?.Expression; - var iteratorItem = Binder.GetUnderlyingCollectionExpressionElement(expr, iteratorBody); + var iteratorItem = element.IteratorBody is { } iteratorBody ? + Binder.GetUnderlyingCollectionExpressionElement(expr, ((BoundExpressionStatement)iteratorBody).Expression, throwOnErrors: false) : + null; var collection = Create(element.Expression); SyntaxNode syntax = element.Syntax; bool isImplicit = element.WasCompilerGenerated; diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 938a600e7fbc5..dadc740f4c93c 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -25102,6 +25102,404 @@ .. GetConfig(), """); } + [Fact] + public void IOperation_AmbiguousAdd_01() + { + string sourceA = """ + using System.Collections; + interface IA { } + interface IB { } + class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + public void Add(IA a) => throw null; + public void Add(IB b) => throw null; + public void Add(object o) => throw null; + } + """; + string sourceB = """ + class C : IA, IB { } + class Program + { + static MyCollection Create(C x, C[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (6,27): error CS0121: The call is ambiguous between the following methods or properties: 'MyCollection.Add(IA)' and 'MyCollection.Add(IB)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "x").WithArguments("MyCollection.Add(IA)", "MyCollection.Add(IB)").WithLocation(6, 27), + // (6,32): error CS0121: The call is ambiguous between the following methods or properties: 'MyCollection.Add(IA)' and 'MyCollection.Add(IB)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "y").WithArguments("MyCollection.Add(IA)", "MyCollection.Add(IB)").WithLocation(6, 32)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: C) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: C) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + + [Fact] + public void IOperation_AmbiguousAdd_02() + { + string sourceA = """ + using System.Collections; + interface IA { } + interface IB { } + class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + public void Add(IA a) => throw null; + public void Add(IB b) => throw null; + } + static class Extensions + { + public static void Add(this MyCollection collection, object o) { } + } + """; + string sourceB = """ + class C : IA, IB { } + class Program + { + static MyCollection Create(C x, C[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (6,27): error CS0121: The call is ambiguous between the following methods or properties: 'MyCollection.Add(IA)' and 'MyCollection.Add(IB)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "x").WithArguments("MyCollection.Add(IA)", "MyCollection.Add(IB)").WithLocation(6, 27), + // (6,32): error CS0121: The call is ambiguous between the following methods or properties: 'MyCollection.Add(IA)' and 'MyCollection.Add(IB)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "y").WithArguments("MyCollection.Add(IA)", "MyCollection.Add(IB)").WithLocation(6, 32)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: C) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: C) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + + [Fact] + public void IOperation_AmbiguousAdd_03() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class ExtensionsA + { + public static void Add(this MyCollection collection, string s) { } + } + static class ExtensionsB + { + public static void Add(this MyCollection collection, string s) { } + } + namespace N + { + static class ExtensionsC + { + public static void Add(this MyCollection collection, T t) { } + } + } + """; + string sourceB = """ + using N; + class Program + { + static MyCollection Create(string x, string[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (6,27): error CS0121: The call is ambiguous between the following methods or properties: 'ExtensionsA.Add(MyCollection, string)' and 'ExtensionsB.Add(MyCollection, string)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "x").WithArguments("ExtensionsA.Add(MyCollection, string)", "ExtensionsB.Add(MyCollection, string)").WithLocation(6, 27), + // (6,32): error CS0121: The call is ambiguous between the following methods or properties: 'ExtensionsA.Add(MyCollection, string)' and 'ExtensionsB.Add(MyCollection, string)' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_AmbigCall, "y").WithArguments("ExtensionsA.Add(MyCollection, string)", "ExtensionsB.Add(MyCollection, string)").WithLocation(6, 32)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.String) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.String, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.String) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.String[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + + [Fact] + public void IOperation_InvalidAdd_01() + { + string sourceA = """ + using System.Collections; + public class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + public static class Extensions + { + public static void Add(this MyCollection collection, string s) { } + } + """; + string sourceB = """ + class Program + { + static MyCollection Create(int x, int[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (5,27): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 27), + // (5,27): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("2", "int", "string").WithLocation(5, 27), + // (5,30): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("2", "int", "string").WithLocation(5, 30), + // (5,32): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 32)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + + [Fact] + public void IOperation_InvalidAdd_02() + { + string sourceA = """ + using System.Collections; + public class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + public static class Extensions + { + public static void Add(this MyCollection collection, params string[] args) { } + } + """; + string sourceB = """ + class Program + { + static MyCollection Create(int x, int[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (5,27): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, params string[])' for the collection initializer has some invalid arguments + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions.Add(MyCollection, params string[])").WithLocation(5, 27), + // (5,27): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("2", "int", "string").WithLocation(5, 27), + // (5,30): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("2", "int", "string").WithLocation(5, 30), + // (5,32): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, params string[])' for the collection initializer has some invalid arguments + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("Extensions.Add(MyCollection, params string[])").WithLocation(5, 32)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + [Fact] public void Async_01() { From 726896e49b211ffb24c50a2cf073d98a2c4ede0d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Sun, 24 Mar 2024 17:32:18 -0700 Subject: [PATCH 03/18] Address feedback --- .../Portable/Binder/Binder_Conversions.cs | 81 +- .../Portable/Binder/Binder_Expressions.cs | 7 + .../Semantics/CollectionExpressionTests.cs | 709 +++++++++++++++++- 3 files changed, 741 insertions(+), 56 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 0454a409555fb..36bf0e26a4e90 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1290,32 +1290,56 @@ internal bool HasCollectionExpressionAddMethod(SyntaxNode syntax, TypeSymbol tar const string methodName = "Add"; var useSiteInfo = CompoundUseSiteInfo.Discarded; - var lookupResult = LookupResult.GetInstance(); - LookupInstanceMember(lookupResult, targetType, leftIsBaseReference: false, rightName: methodName, rightArity: 0, invoked: true, ref useSiteInfo); - bool anyApplicable = lookupResult.IsMultiViable && - lookupResult.Symbols.Any(s => s is MethodSymbol m && isApplicableAddMethod(m, expectingExtensionMethod: false)); - lookupResult.Free(); - if (anyApplicable) + var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; + var memberAccess = BindInstanceMemberAccess( + syntax, + right: syntax, + boundLeft: implicitReceiver, + rightName: methodName, + rightArity: 0, + typeArgumentsSyntax: default, + typeArgumentsWithAnnotations: default, + invoked: true, + indexed: false, + BindingDiagnosticBag.Discarded); + if (memberAccess is not BoundMethodGroup methodGroup) + { + return false; + } + + Debug.Assert(methodGroup.SearchExtensionMethods); + + if (methodGroup.ResultKind == LookupResultKind.Viable && + methodGroup.Methods.Any(m => isApplicableAddMethod(m.GetConstructedLeastOverriddenMethod(accessingTypeOpt: null, requireSameReturnType: false), expectingExtensionMethod: false))) { return true; } - var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; - foreach (var scope in new ExtensionMethodScopes(this)) + if (methodGroup.SearchExtensionMethods && + hasApplicableAddExtensionMethod(syntax, implicitReceiver)) { - var methodGroup = MethodGroup.GetInstance(); - PopulateExtensionMethodsFromSingleBinder(scope, methodGroup, syntax, implicitReceiver, rightName: methodName, typeArgumentsWithAnnotations: default, BindingDiagnosticBag.Discarded); - anyApplicable = methodGroup.Methods.Any(m => isApplicableAddMethod(m, expectingExtensionMethod: true)); - methodGroup.Free(); - if (anyApplicable) - { - return true; - } + return true; } return false; - static bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMethod) + bool hasApplicableAddExtensionMethod(SyntaxNode syntax, BoundObjectOrCollectionValuePlaceholder implicitReceiver) + { + foreach (var scope in new ExtensionMethodScopes(this)) + { + var methodGroup = MethodGroup.GetInstance(); + PopulateExtensionMethodsFromSingleBinder(scope, methodGroup, syntax, implicitReceiver, rightName: methodName, typeArgumentsWithAnnotations: default, BindingDiagnosticBag.Discarded); + bool anyApplicable = methodGroup.Methods.Any(m => isApplicableAddMethod(m, expectingExtensionMethod: true)); + methodGroup.Free(); + if (anyApplicable) + { + return true; + } + } + return false; + } + + bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMethod) { if (method.IsStatic != expectingExtensionMethod) { @@ -1331,10 +1355,21 @@ static bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMe } // Any trailing parameters must be optional or params. - for (int i = requiredLength; i < parameters.Length; i++) + int optionalLength = parameters.Length - (OverloadResolution.IsValidParams(this, method) ? 1 : 0); + for (int i = requiredLength; i < optionalLength; i++) + { + if (parameters[i] is not ({ IsOptional: true, RefKind: RefKind.None or RefKind.In or RefKind.RefReadOnlyParameter })) + { + return false; + } + } + + // Extension method 'this' parameter must be by value, ref, in, or ref readonly. + if (expectingExtensionMethod) { - if (parameters[i] is { IsOptional: false, IsParams: false }) + if (parameters[0].RefKind is not (RefKind.None or RefKind.Ref or RefKind.In or RefKind.RefReadOnlyParameter)) { + Debug.Assert(false); // We should have treated this method as unsupported. Add a corresponding test. return false; } } @@ -1345,14 +1380,16 @@ static bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMe return false; } - // If the method is generic, can the type arguments be inferred from the one or two arguments? + // If the method is generic, fail if there are type arguments that are not referenced + // in the required parameters types. That is, fail if we know the type arguments cannot + // be inferred from the arguments. var typeParameters = method.TypeParameters; if (typeParameters.Length > 0) { - var usedParameterTypes = parameters.Slice(0, requiredLength).SelectAsArray(p => p.Type); + var requiredParameters = parameters.AsSpan(0, requiredLength); foreach (var typeParameter in typeParameters) { - if (!usedParameterTypes.Any((parameterType, typeParameter) => parameterType.ContainsTypeParameter(typeParameter), typeParameter)) + if (requiredParameters.All(typeParameter, (parameter, typeParameter) => !parameter.Type.ContainsTypeParameter(typeParameter))) { // The type parameter does not appear in any of the parameter types. return false; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index c577341e48531..13d3755d950e0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -7915,6 +7915,13 @@ protected MethodGroupResolution BindExtensionMethod( bool withDependencies, in CallingConventionInfo callingConvention = default) { + // + // !!! ATTENTION !!! + // + // This function should be kept in sync with local function + // HasCollectionExpressionAddMethod.hasApplicableAddExtensionMethod. + // + Debug.Assert((options & ~(OverloadResolution.Options.IsMethodGroupConversion | OverloadResolution.Options.IsFunctionPointerResolution | OverloadResolution.Options.InferWithDynamic | diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index dadc740f4c93c..9066ea0ea311d 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -27208,7 +27208,7 @@ class MyCollection2 : IEnumerable where TAdd : TElemen [Fact] public void GenericIEnumerable_DifferentConversionToAdd() { - // For purpose of conversion, we rely the existence of an Add method. + // For purpose of conversion, we rely on the existence of an Add method. // But for purpose of construction, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) string source = """ using System.Collections; @@ -27236,7 +27236,7 @@ class MyCollection : IEnumerable [Fact] public void GenericIEnumerable_NoConversionToAdd() { - // For purpose of conversion, we rely the existence of an Add method. + // For purpose of conversion, we rely on the existence of an Add method. // But for purpose of construction, there is no conversion from uint to sbyte (from Add(sbyte)) string source = """ using System.Collections; @@ -34718,7 +34718,7 @@ static void Main() } [Fact] - public void AddMethod_Accessibility() + public void AddMethod_Accessibility_01() { string sourceA = """ using System.Collections; @@ -34772,7 +34772,7 @@ static void Main() } [Fact] - public void AddMethod_Extension_Accessibility() + public void AddMethod_Accessibility_02() { string sourceA = """ using System.Collections; @@ -34814,6 +34814,52 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); } + [Fact] + public void AddMethod_Accessibility_03() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollectionBase : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + protected void Add(T t) { _list.Add(t); } + } + class MyCollection : MyCollectionBase + { + internal void __AddInternal(T t) { Add(t); } + } + """; + string sourceB = """ + static class Extensions + { + public static void Add(this MyCollection c, T t) { c.__AddInternal(t); } + } + """; + string sourceC = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + + CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + var comp = CreateCompilation([sourceA, sourceC, s_collectionExtensions]); + comp.VerifyEmitDiagnostics( + // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + } + [Fact] public void AddMethod_Overloads() { @@ -35309,17 +35355,20 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); } - [Fact] - public void AddMethod_02() + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_02A(string refKind) { - string source = """ + string source = $$""" using System.Collections; using System.Collections.Generic; class MyCollection : IEnumerable { private readonly List _list = new(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); - public void Add(T t, int x = 1, int y = 2) { _list.Add(t); } + public void Add(T t, {{refKind}} int x = 1, {{refKind}} int y = 2) { _list.Add(t); } } class Program { @@ -35336,16 +35385,93 @@ static void Main() } [Fact] - public void AddMethod_03() + public void AddMethod_02B() { string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T t, int x = 1); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(T t, int x) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,33): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 33), + // (19,38): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "y").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 38), + // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(20, 40)); + } + + [Fact] + public void AddMethod_02C() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T t, int x); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(T t, int x = 1) { _list.Add(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32)); + } + + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_03A(string refKind) + { + string source = $$""" using System.Collections; using System.Collections.Generic; class MyCollection : IEnumerable { private readonly List _list = new(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); - public void Add(T t, int x, int y = 2) { _list.Add(t); } + public void Add(T t, {{refKind}} int x, {{refKind}} int y = 2) { _list.Add(t); } } class Program { @@ -35358,23 +35484,89 @@ static void Main() } """; var comp = CreateCompilation(source); + if (refKind == "ref readonly") + { + comp.VerifyEmitDiagnostics( + // (7,67): 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 void Add(T t, ref readonly int x, ref readonly int y = 2) { _list.Add(t); } + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "2").WithArguments("y").WithLocation(7, 67), + // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + } + else + { + comp.VerifyEmitDiagnostics( + // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + } + } + + [Theory] + [CombinatorialData] + public void AddMethod_03B(bool useOut) + { + // public struct MyCollection : IEnumerable + // { + // IEnumerator IEnumerable.GetEnumerator() => null; + // public void Add(T t, ref int index = 0) => throw null; + // } + string sourceA = $$""" + .class public sealed MyCollection`1 + extends [mscorlib]System.ValueType + implements [mscorlib]System.Collections.IEnumerable + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method private instance class [mscorlib]System.Collections.IEnumerator GetEnumerator() + { + .override [mscorlib]System.Collections.IEnumerable::GetEnumerator + ldnull + ret + } + .method public instance void Add(!T t, {{(useOut ? "[out]" : "")}} [opt] int32& index) + { + .param [2] = int32(0x00000000) + ldnull + ret + } + } + """; + var refA = CompileIL(sourceA); + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation(sourceB, references: [refA]); comp.VerifyEmitDiagnostics( - // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. - // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); } [Fact] - public void AddMethod_04() + public void AddMethod_04A() { string sourceA = """ using System.Collections; using System.Collections.Generic; - class MyCollection : IEnumerable + abstract class MyCollectionBase + { + public abstract void Add(params T[] args); + } + class MyCollection : MyCollectionBase, IEnumerable { private readonly List _list = new(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); - public void Add(params T[] args) + public override void Add(T[] args) { if (args is null) return; _list.AddRange(args); @@ -35412,16 +35604,69 @@ static void Main() } [Fact] - public void AddMethod_05() + public void AddMethod_04B() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T[] args); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(params T[] args) + { + if (args is null) return; + _list.AddRange(args); + } + } + """; + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB]); + comp.VerifyEmitDiagnostics( + // (7,33): error CS1950: The best overloaded Add method 'MyCollection.Add(int?[])' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(int?[])").WithLocation(7, 33), + // (7,33): error CS1503: Argument 1: cannot convert from 'int' to 'int?[]' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "int", "int?[]").WithLocation(7, 33), + // (7,36): error CS1503: Argument 1: cannot convert from 'int' to 'int?[]' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("1", "int", "int?[]").WithLocation(7, 36), + // (7,38): error CS1950: The best overloaded Add method 'MyCollection.Add(int?[])' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(int?[])").WithLocation(7, 38)); + } + + [Fact] + public void AddMethod_05A() { string source = """ using System.Collections; using System.Collections.Generic; - class MyCollection : IEnumerable + abstract class MyCollectionBase + { + public abstract void Add(T x, params T[] y); + } + class MyCollection : MyCollectionBase, IEnumerable { private readonly List _list = new(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); - public void Add(T x, params T[] y) { _list.Add(x); _list.AddRange(y); } + public override void Add(T x, T[] y) { _list.Add(x); _list.AddRange(y); } } class Program { @@ -35438,7 +35683,117 @@ static void Main() } [Fact] - public void AddMethod_06() + public void AddMethod_05B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T x, T[] y); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(T x, params T[] y) { _list.Add(x); _list.AddRange(y); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y, null]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + + [Fact] + public void AddMethod_06A() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T x, T y = default, params T[] z); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(T x, T y, T[] z) { _list.Add(x); _list.Add(y); _list.AddRange(z); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,33): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 33), + // (19,38): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "y").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 38), + // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(20, 40)); + } + + [Fact] + public void AddMethod_06B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class MyCollectionBase + { + public abstract void Add(T x, T y, T[] z); + } + class MyCollection : MyCollectionBase, IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public override void Add(T x, T y = default, params T[] z) { _list.Add(x); _list.Add(y); _list.AddRange(z); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'z' of 'MyCollection.Add(int?, int?, int?[])' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("z", "MyCollection.Add(int?, int?, int?[])").WithLocation(20, 40)); + } + + [Fact] + public void AddMethod_07() { string sourceA = """ using System.Collections; @@ -35493,7 +35848,7 @@ static void Main() } [Fact] - public void AddMethod_07() + public void AddMethod_08() { string sourceA = """ using System.Collections; @@ -35552,6 +35907,177 @@ static void Main() Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("MyCollection.Add(string)").WithLocation(7, 40)); } + [Fact] + public void AddMethod_09() + { + // public struct MyCollection : IEnumerable + // { + // IEnumerator IEnumerable.GetEnumerator() => null; + // public void Add(T x, params T y) => throw null; + // } + string sourceA = $$""" + .class public sealed MyCollection`1 + extends [mscorlib]System.ValueType + implements [mscorlib]System.Collections.IEnumerable + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method private instance class [mscorlib]System.Collections.IEnumerator GetEnumerator() + { + .override [mscorlib]System.Collections.IEnumerable::GetEnumerator + ldnull + ret + } + .method public instance void Add(!T x, !T y) + { + .param [2] + .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00 ) + ldnull + ret + } + } + """; + var refA = CompileIL(sourceA); + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation(sourceB, references: [refA]); + comp.VerifyEmitDiagnostics( + // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + } + + [Fact] + public void AddMethod_ParamCollectionAttribute_01() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T x, params List y) + { + _list.Add(x); + foreach (var i in y) + _list.Add(i); + } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceB1, sourceA, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_ParamCollectionAttribute_02() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(U x, params MyCollection y) where U : T + { + _list.Add(x); + foreach (var i in y) + _list.Add(i); + } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceB1, sourceA, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_ParamCollectionAttribute_03() + { + // public struct MyCollection : IEnumerable + // { + // IEnumerator IEnumerable.GetEnumerator() => null; + // public void Add(object x, [ParamCollection] object y) => throw null; + // } + string sourceA = $$""" + .class public System.Runtime.CompilerServices.ParamCollectionAttribute extends [mscorlib]System.Attribute + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + } + .class public sealed MyCollection`1 + extends [mscorlib]System.ValueType + implements [mscorlib]System.Collections.IEnumerable + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method private instance class [mscorlib]System.Collections.IEnumerator GetEnumerator() + { + .override [mscorlib]System.Collections.IEnumerable::GetEnumerator + ldnull + ret + } + .method public instance void Add(object x, object y) + { + .param [2] + .custom instance void System.Runtime.CompilerServices.ParamCollectionAttribute::.ctor() = ( 01 00 00 00 ) + ldnull + ret + } + } + """; + var refA = CompileIL(sourceA); + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation(sourceB, references: [refA]); + comp.VerifyEmitDiagnostics( + // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + } + [Fact] public void AddMethod_Extension_01() { @@ -35585,10 +36111,13 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } - [Fact] - public void AddMethod_Extension_02() + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_Extension_02(string refKind) { - string source = """ + string source = $$""" using System.Collections; using System.Collections.Generic; class MyCollection : IEnumerable @@ -35599,7 +36128,7 @@ class MyCollection : IEnumerable } static class Extensions { - public static void Add(this MyCollection collection, T t, int x = 1, int y = 2) { collection.__AddInternal(t); } + public static void Add(this MyCollection collection, T t, {{refKind}} int x = 1, {{refKind}} int y = 2) { collection.__AddInternal(t); } } class Program { @@ -35615,10 +36144,13 @@ static void Main() CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, 2, 3, null], "); } - [Fact] - public void AddMethod_Extension_03() + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref readonly")] + public void AddMethod_Extension_03(string refKind) { - string source = """ + string source = $$""" using System.Collections; using System.Collections.Generic; class MyCollection : IEnumerable @@ -35629,7 +36161,7 @@ class MyCollection : IEnumerable } static class Extensions { - public static void Add(this MyCollection collection, T t, int x, int y = 2) { collection.__AddInternal(t); } + public static void Add(this MyCollection collection, T t, {{refKind}} int x, {{refKind}} int y = 2) { collection.__AddInternal(t); } } class Program { @@ -35642,10 +36174,23 @@ static void Main() } """; var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. - // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + if (refKind == "ref readonly") + { + comp.VerifyEmitDiagnostics( + // (11,110): 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 void Add(this MyCollection collection, T t, ref readonly int x, ref readonly int y = 2) { collection.__AddInternal(t); } + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "2").WithArguments("y").WithLocation(11, 110), + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + else + { + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } } [Fact] @@ -35737,6 +36282,42 @@ static void Main() [Fact] public void AddMethod_Extension_06() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T x, T y = default, params T[] z) + { + collection.__AddInternal(x); + collection.__AddInternal(y); + foreach (var a in z) + collection.__AddInternal(a); + } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[1, null, 2, null, 3, null], "); + } + + [Fact] + public void AddMethod_Extension_07() { string sourceA = """ using System.Collections; @@ -35798,7 +36379,7 @@ static void Main() [InlineData("in")] [InlineData("ref")] [InlineData("ref readonly")] - public void AddMethod_Extension_07(string refKind) + public void AddMethod_Extension_08(string refKind) { string source = $$""" using System.Collections; @@ -35829,6 +36410,66 @@ static void Main() CompileAndVerify([source, s_collectionExtensions], expectedOutput: expectedOutput); } + [Fact] + public void AddMethod_Extension_09() + { + // public struct MyCollection : IEnumerable + // { + // IEnumerator IEnumerable.GetEnumerator() => null; + // } + // public static class Extensions + // { + // public static void Add(this out MyCollection collection, T t) => throw null; + // } + string sourceA = """ + .assembly extern mscorlib { .ver 4:0:0:0 .publickeytoken = (B7 7A 5C 56 19 34 E0 89) } + .assembly '<>' + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + } + .class public sealed MyCollection`1 + extends [mscorlib]System.ValueType + implements [mscorlib]System.Collections.IEnumerable + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method private instance class [mscorlib]System.Collections.IEnumerator GetEnumerator() + { + .override [mscorlib]System.Collections.IEnumerable::GetEnumerator + ldnull + ret + } + } + .class public abstract sealed Extensions + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig static void Add([out] valuetype MyCollection`1& collection, !!T t) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + ldnull + throw + } + } + """; + var refA = CompileIL(sourceA, prependDefaultHeader: false); + + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation(sourceB, references: [refA]); + comp.VerifyEmitDiagnostics( + // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + } + [Fact] public void AddMethod_Base() { From 357dc530843113ec9a3cbd45dbf81ac832f0960b Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:55:47 -0700 Subject: [PATCH 04/18] Address feedback --- .../Semantics/CollectionExpressionTests.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 9066ea0ea311d..a1708506bb715 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -37262,6 +37262,60 @@ static void Main() Diagnostic(ErrorCode.ERR_NoTypeDef, "y").WithArguments("A", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 40)); } + [Fact] + public void AddMethod_UseSiteErrors_ParamCollection() + { + string assemblyA = GetUniqueName(); + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollectionA : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t) { _list.Add(t); } + } + """; + var comp = CreateCompilation(sourceA, assemblyName: assemblyA); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollectionB : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(U x, params MyCollectionA y) where U : T { _list.Add(x); _list.AddRange(y); } + } + """; + comp = CreateCompilation(sourceB, references: [refA]); + var refB = comp.EmitToImageReference(); + + string sourceC = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollectionB z = [x, ..y]; + z.Report(); + } + } + """; + + CompileAndVerify([sourceC, s_collectionExtensions], references: [refA, refB], expectedOutput: "[1, 2, 3], "); + + comp = CreateCompilation([sourceC, s_collectionExtensions], references: [refB]); + comp.VerifyEmitDiagnostics( + // (7,35): error CS9230: Collection expression type 'MyCollectionB' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollectionB z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollectionB").WithLocation(7, 35)); + } + [Fact] public void SynthesizedReadOnlyList_SingleElement() { From aa38c7ff07a83f22ec76842985e08aa2658e7470 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:15:47 -0700 Subject: [PATCH 05/18] Add comments and asserts to GetUnderlyingCollectionExpressionElement --- .../CSharp/Portable/Binder/Binder_Conversions.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 36bf0e26a4e90..d3f1a72e6ffc1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1417,18 +1417,26 @@ internal static BoundExpression GetUnderlyingCollectionExpressionElement(BoundCo case BoundDynamicCollectionElementInitializer dynamicInitializer: return dynamicInitializer.Arguments[0]; } + if (throwOnErrors) { throw ExceptionUtilities.UnexpectedValue(element); } + + // Handle error cases from bindCollectionInitializerElementAddMethod. switch (element) { case BoundCall call: + // Overload resolution failed with one or more applicable or ambiguous + // Add methods. This case can be hit for spreads and non-spread elements. + Debug.Assert(call.HasErrors); return call.Arguments[call.InvokedAsExtensionMethod ? 1 : 0]; default: + Debug.Assert(element.Kind == BoundKind.BadExpression); return element; } } + return element; static BoundExpression getCollectionInitializerElement(BoundCollectionElementInitializer collectionInitializer) From 9d7e2764d332b302acd8bffe35eb1d9d2b406a9d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:46:46 -0700 Subject: [PATCH 06/18] Improve checks in GetUnderlyingCollectionExpressionElement --- .../Portable/Binder/Binder_Conversions.cs | 7 +- .../Semantics/CollectionExpressionTests.cs | 216 ++++++++++++++++-- 2 files changed, 199 insertions(+), 24 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index d3f1a72e6ffc1..6919e905f054b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1430,10 +1430,13 @@ internal static BoundExpression GetUnderlyingCollectionExpressionElement(BoundCo // Overload resolution failed with one or more applicable or ambiguous // Add methods. This case can be hit for spreads and non-spread elements. Debug.Assert(call.HasErrors); + Debug.Assert(call.Method.Name == "Add"); return call.Arguments[call.InvokedAsExtensionMethod ? 1 : 0]; + case BoundBadExpression badExpression: + Debug.Assert(false); // Add test if we hit this assert. + return badExpression; default: - Debug.Assert(element.Kind == BoundKind.BadExpression); - return element; + throw ExceptionUtilities.UnexpectedValue(element); } } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index a1708506bb715..07417463ab3a8 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -25344,6 +25344,96 @@ static MyCollection Create(string x, string[] y) [Fact] public void IOperation_InvalidAdd_01() + { + string sourceA = """ + using System.Collections; + public class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + public void Add(string s) { } + } + """; + string sourceB = """ + class Program + { + static MyCollection Create() + { + return /**/[F1(), ..F2()]/**/; + } + static int F1() => 1; + static int[] F2() => [2, 3]; + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (5,27): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "F1()").WithArguments("MyCollection.Add(string)").WithLocation(5, 27), + // (5,27): error CS1503: Argument 1: cannot convert from 'int' to 'string' + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "F1()").WithArguments("1", "int", "string").WithLocation(5, 27), + // (5,33): error CS1503: Argument 1: cannot convert from 'int' to 'string' + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "..F2()").WithArguments("1", "int", "string").WithLocation(5, 33), + // (5,35): error CS1950: The best overloaded Add method 'MyCollection.Add(string)' for the collection initializer has some invalid arguments + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "F2()").WithArguments("MyCollection.Add(string)").WithLocation(5, 35)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[F1(), ..F2()]') + Elements(2): + IInvocationOperation (System.Int32 Program.F1()) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'F1()') + Instance Receiver: + null + Arguments(0) + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..F2()') + Operand: + IInvocationOperation (System.Int32[] Program.F2()) (OperationKind.Invocation, Type: System.Int32[], IsInvalid) (Syntax: 'F2()') + Instance Receiver: + null + Arguments(0) + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[F1(), ..F2()]') + Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (CollectionExpression) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[F1(), ..F2()]') + Elements(2): + IInvocationOperation (System.Int32 Program.F1()) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'F1()') + Instance Receiver: + null + Arguments(0) + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..F2()') + Operand: + IInvocationOperation (System.Int32[] Program.F2()) (OperationKind.Invocation, Type: System.Int32[], IsInvalid) (Syntax: 'F2()') + Instance Receiver: + null + Arguments(0) + ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (Identity) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + + [Fact] + public void IOperation_InvalidAdd_02() { string sourceA = """ using System.Collections; @@ -25359,35 +25449,43 @@ public static void Add(this MyCollection collection, string s) { } string sourceB = """ class Program { - static MyCollection Create(int x, int[] y) + static MyCollection Create() { - return /**/[x, ..y]/**/; + return /**/[F1(), ..F2()]/**/; } + static int F1() => 1; + static int[] F2() => [2, 3]; } """; var comp = CreateCompilation([sourceB, sourceA]); comp.VerifyEmitDiagnostics( // (5,27): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments - // return /**/[x, ..y]/**/; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 27), + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "F1()").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 27), // (5,27): error CS1503: Argument 2: cannot convert from 'int' to 'string' - // return /**/[x, ..y]/**/; - Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("2", "int", "string").WithLocation(5, 27), - // (5,30): error CS1503: Argument 2: cannot convert from 'int' to 'string' - // return /**/[x, ..y]/**/; - Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("2", "int", "string").WithLocation(5, 30), - // (5,32): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments - // return /**/[x, ..y]/**/; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 32)); + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "F1()").WithArguments("2", "int", "string").WithLocation(5, 27), + // (5,33): error CS1503: Argument 2: cannot convert from 'int' to 'string' + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgType, "..F2()").WithArguments("2", "int", "string").WithLocation(5, 33), + // (5,35): error CS1950: The best overloaded Add method 'Extensions.Add(MyCollection, string)' for the collection initializer has some invalid arguments + // return /**/[F1(), ..F2()]/**/; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "F2()").WithArguments("Extensions.Add(MyCollection, string)").WithLocation(5, 35)); VerifyOperationTreeForTest(comp, """ - ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[F1(), ..F2()]') Elements(2): - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') - ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + IInvocationOperation (System.Int32 Program.F1()) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'F1()') + Instance Receiver: + null + Arguments(0) + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..F2()') Operand: - IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + IInvocationOperation (System.Int32[] Program.F2()) (OperationKind.Invocation, Type: System.Int32[], IsInvalid) (Syntax: 'F2()') + Instance Receiver: + null + Arguments(0) ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) (Identity) """); @@ -25403,16 +25501,22 @@ static MyCollection Create(int x, int[] y) Predecessors: [B0] Statements (0) Next (Return) Block[B2] - IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[F1(), ..F2()]') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) (CollectionExpression) Operand: - ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + ICollectionExpressionOperation (2 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[F1(), ..F2()]') Elements(2): - IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') - ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + IInvocationOperation (System.Int32 Program.F1()) (OperationKind.Invocation, Type: System.Int32, IsInvalid) (Syntax: 'F1()') + Instance Receiver: + null + Arguments(0) + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..F2()') Operand: - IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + IInvocationOperation (System.Int32[] Program.F2()) (OperationKind.Invocation, Type: System.Int32[], IsInvalid) (Syntax: 'F2()') + Instance Receiver: + null + Arguments(0) ElementConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) (Identity) Block[B2] - Exit @@ -25422,7 +25526,7 @@ static MyCollection Create(int x, int[] y) } [Fact] - public void IOperation_InvalidAdd_02() + public void IOperation_InvalidAdd_03() { string sourceA = """ using System.Collections; @@ -25500,6 +25604,74 @@ static MyCollection Create(int x, int[] y) """); } + [Fact] + public void IOperation_InvalidAdd_04() + { + string sourceA = """ + using System; + using System.Collections; + public class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + public Action Add; + } + """; + string sourceB = """ + class Program + { + static MyCollection Create(int x, int[] y) + { + return /**/[x, ..y]/**/; + } + } + """; + var comp = CreateCompilation([sourceB, sourceA]); + comp.VerifyEmitDiagnostics( + // (5,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(5, 26)); + + VerifyOperationTreeForTest(comp, + """ + ICollectionExpressionOperation (2 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (NoConversion) + """); + + var tree = comp.SyntaxTrees[0]; + var method = tree.GetRoot().DescendantNodes().OfType().Single(m => m.Identifier.Text == "Create"); + VerifyFlowGraph(comp, method, + """ + Block[B0] - Entry + Statements (0) + Next (Regular) Block[B1] + Block[B1] - Block + Predecessors: [B0] + Statements (0) + Next (Return) Block[B2] + IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: MyCollection, IsInvalid, IsImplicit) (Syntax: '[x, ..y]') + Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (NoConversion) + Operand: + ICollectionExpressionOperation (2 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[x, ..y]') + Elements(2): + IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32, IsInvalid) (Syntax: 'x') + ISpreadOperation (ElementType: System.Int32) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..y') + Operand: + IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: System.Int32[], IsInvalid) (Syntax: 'y') + ElementConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + (NoConversion) + Block[B2] - Exit + Predecessors: [B1] + Statements (0) + """); + } + [Fact] public void Async_01() { From 75978ab9bc5bc1d1cd965ef358ceb1549ff1fe52 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:30:24 -0700 Subject: [PATCH 07/18] Address feedback --- .../Emit2/Semantics/CollectionExpressionTests.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 07417463ab3a8..e23fcfbdedd4b 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -35714,6 +35714,7 @@ static void Main() int x = 1; int[] y = [2, 3]; MyCollection z = [x, ..y]; + MyCollection w = new() { x }; } } """; @@ -35721,7 +35722,10 @@ static void Main() comp.VerifyEmitDiagnostics( // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), + // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'index' of 'MyCollection.Add(int, ref int)' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("index", $"MyCollection.Add(int, {(useOut ? "out" : "ref")} int)").WithLocation(8, 39)); } [Fact] @@ -36118,6 +36122,7 @@ static void Main() int x = 1; int[] y = [2, 3]; MyCollection z = [x, ..y]; + MyCollection w = new() { x }; } } """; @@ -36125,7 +36130,10 @@ static void Main() comp.VerifyEmitDiagnostics( // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), + // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int, params int)' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int, params int)").WithLocation(8, 39)); } [Fact] From 90448077d12f37eaf8c961e84ec3bb5cbb643e3e Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 26 Mar 2024 13:44:40 -0700 Subject: [PATCH 08/18] Add extension method test for class 'this' type by reference --- .../Semantics/CollectionExpressionTests.cs | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index e23fcfbdedd4b..0b49246f0653c 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -36559,7 +36559,7 @@ static void Main() [InlineData("in")] [InlineData("ref")] [InlineData("ref readonly")] - public void AddMethod_Extension_08(string refKind) + public void AddMethod_Extension_08A(string refKind) { string source = $$""" using System.Collections; @@ -36590,6 +36590,66 @@ static void Main() CompileAndVerify([source, s_collectionExtensions], expectedOutput: expectedOutput); } + [Theory] + [InlineData("")] + [InlineData("in")] + [InlineData("ref")] + [InlineData("ref readonly")] + public void AddMethod_Extension_08B(string refKind) + { + string source = $$""" + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private List _list; + IEnumerator IEnumerable.GetEnumerator() => GetList().GetEnumerator(); + internal void __AddInternal(T t) { GetList().Add(t); } + private List GetList() => _list ??= new(); + } + static class Extensions + { + public static void Add(this {{refKind}} MyCollection collection, T t) { collection.__AddInternal(t); } + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + var comp = CreateCompilation([source, s_collectionExtensions], options: TestOptions.ReleaseExe); + switch (refKind) + { + case "": + CompileAndVerify(comp, expectedOutput: "[1, 2, 3], "); + break; + case "in": + case "ref readonly": + comp.VerifyEmitDiagnostics( + // (12,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'Add' must be a concrete (non-generic) value type. + // public static void Add(this in MyCollection collection, T t) { collection.__AddInternal(t); } + Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "Add").WithArguments("Add").WithLocation(12, 24), + // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); + break; + case "ref": + comp.VerifyEmitDiagnostics( + // (12,24): error CS8337: The first parameter of a 'ref' extension method 'Add' must be a value type or a generic type constrained to struct. + // public static void Add(this ref MyCollection collection, T t) { collection.__AddInternal(t); } + Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "Add").WithArguments("Add").WithLocation(12, 24), + // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); + break; + } + } + [Fact] public void AddMethod_Extension_09() { From 387cb373035ad8bbc188d149f40a2d6838b5a32a Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 26 Mar 2024 19:37:25 -0700 Subject: [PATCH 09/18] Use overload resolution for figuring out applicable `Add` methods --- .../Portable/Binder/Binder_Conversions.cs | 318 +++++++-------- .../Portable/Binder/Binder_Expressions.cs | 15 +- .../Portable/Binder/Binder_Invocation.cs | 16 +- .../Semantics/Conversions/Conversions.cs | 4 +- .../OverloadResolution/OverloadResolution.cs | 29 +- .../OverloadResolutionResult.cs | 30 +- .../Symbols/ReducedExtensionMethodSymbol.cs | 4 +- .../Source/SourceComplexParameterSymbol.cs | 4 +- .../Semantics/CollectionExpressionTests.cs | 376 +++++++++++++++--- 9 files changed, 527 insertions(+), 269 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index d3f1a72e6ffc1..53fbb46a5c233 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -944,7 +944,7 @@ private bool HasParamsCollectionTypeInProgress(NamedTypeSymbol toCheck) return false; } - internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, TypeSymbol targetType, TypeSymbol elementType, out ImmutableArray addMethods, BindingDiagnosticBag diagnostics) + internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, TypeSymbol targetType, out ImmutableArray addMethods, BindingDiagnosticBag diagnostics) { Debug.Assert(!targetType.IsDynamic()); @@ -958,7 +958,12 @@ internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, Type } var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; - var elementPlaceholder = new BoundValuePlaceholder(syntax, elementType) { WasCompilerGenerated = true }; + + // For the element, we create a dynamic argument and will be forcing overload resolution to convert it to any type. + // This way we are going to do most of the work in terms of determining applicability of 'Add' method candidates + // in overload resolution. + var elementPlaceholder = new BoundValuePlaceholder(syntax, Compilation.DynamicType) { WasCompilerGenerated = true }; + var addMethodBinder = WithAdditionalFlags(BinderFlags.CollectionInitializerAddMethod | BinderFlags.CollectionExpressionConversionValidation); if (namedType is not null) @@ -1047,19 +1052,6 @@ static bool bindInvocationExpression( diagnostics, out addMethods); } - // This is what BindDynamicInvocation is doing in terms of reporting diagnostics and detecting a failure - static bool bindDynamicInvocation( - Binder addMethodBinder, - SyntaxNode node, - AnalyzedArguments arguments, - BindingDiagnosticBag diagnostics) - { - ImmutableArray argArray = addMethodBinder.BuildArgumentsForDynamicInvocation(arguments, diagnostics); - var refKindsArray = arguments.RefKinds.ToImmutableOrNull(); - - return !ReportBadDynamicArguments(node, argArray, refKindsArray, diagnostics, queryClause: null); - } - // This is what BindMethodGroupInvocation is doing in terms of reporting diagnostics and detecting a failure static bool bindMethodGroupInvocation( Binder addMethodBinder, @@ -1070,12 +1062,14 @@ static bool bindMethodGroupInvocation( BindingDiagnosticBag diagnostics, out ImmutableArray addMethods) { + Debug.Assert(methodGroup.ReceiverOpt is not null); + bool result; CompoundUseSiteInfo useSiteInfo = addMethodBinder.GetNewCompoundUseSiteInfo(diagnostics); var resolution = addMethodBinder.ResolveMethodGroup( methodGroup, expression, WellKnownMemberNames.CollectionInitializerAddMethodName, analyzedArguments, useSiteInfo: ref useSiteInfo, - options: (analyzedArguments.HasDynamicArgument ? OverloadResolution.Options.DynamicResolution : OverloadResolution.Options.None)); + options: OverloadResolution.Options.DynamicResolution | OverloadResolution.Options.DynamicConvertsToAnything); diagnostics.Add(expression, useSiteInfo); @@ -1100,10 +1094,11 @@ static bool bindMethodGroupInvocation( } else { + Debug.Assert(resolution.AnalyzedArguments.HasDynamicArgument); + // If overload resolution found one or more applicable methods and at least one argument // was dynamic then treat this as a dynamic call. - if (resolution.AnalyzedArguments.HasDynamicArgument && - resolution.OverloadResolutionResult.HasAnyApplicableMember) + if (resolution.OverloadResolutionResult.HasAnyApplicableMember) { // Note that the runtime binder may consider candidates that haven't passed compile-time final validation // and an ambiguity error may be reported. Also additional checks are performed in runtime final validation @@ -1132,28 +1127,8 @@ static bool bindMethodGroupInvocation( { Debug.Assert(finalApplicableCandidates.Length > 0); - if (resolution.IsExtensionMethodGroup) - { - // error CS1973: 'T' has no applicable method named 'M' but appears to have an - // extension method by that name. Extension methods cannot be dynamically dispatched. Consider - // casting the dynamic arguments or calling the extension method without the extension method - // syntax. - - // We found an extension method, so the instance associated with the method group must have - // existed and had a type. - Debug.Assert(methodGroup.InstanceOpt?.Type is not null); - - Error(diagnostics, ErrorCode.ERR_BadArgTypeDynamicExtension, syntax, methodGroup.InstanceOpt.Type, methodGroup.Name); - addMethods = []; - result = false; - } - else - { - addMethodBinder.ReportDynamicInvocationWarnings(syntax, methodGroup, diagnostics, resolution, finalApplicableCandidates); - - addMethods = finalApplicableCandidates.SelectAsArray(r => r.Member); - result = bindDynamicInvocation(addMethodBinder, syntax, resolution.AnalyzedArguments, diagnostics); - } + addMethods = filterOutBadGenericMethods(addMethodBinder, syntax, methodGroup, resolution, finalApplicableCandidates, ref useSiteInfo); + result = !addMethods.IsEmpty; } } else @@ -1175,6 +1150,149 @@ static bool bindMethodGroupInvocation( return result; } + static ImmutableArray filterOutBadGenericMethods( + Binder addMethodBinder, SyntaxNode syntax, BoundMethodGroup methodGroup, MethodGroupResolution resolution, + ImmutableArray> finalApplicableCandidates, ref CompoundUseSiteInfo useSiteInfo) + { + Debug.Assert(methodGroup.ReceiverOpt is not null); + + ImmutableArray addMethods; + var resultBuilder = ArrayBuilder.GetInstance(finalApplicableCandidates.Length); + + foreach (var candidate in finalApplicableCandidates) + { + // If the method is generic, skip it if the type arguments cannot be inferred. + var typeParameters = candidate.Member.TypeParameters; + + if (!typeParameters.IsEmpty) + { + if (resolution.IsExtensionMethodGroup) + { + // We need to validate an ability to infer type arguments as well as check conversion to 'this' parameter. + // Overload resolution doesn't check the conversion when 'this' type refers to a type parameter + TypeSymbol? receiverType = methodGroup.ReceiverOpt.Type; + Debug.Assert(receiverType is not null); + bool thisTypeIsOpen = typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[0]); + MethodSymbol? constructed = null; + bool wasFullyInferred = false; + + if (thisTypeIsOpen) + { + constructed = ReducedExtensionMethodSymbol.InferExtensionMethodTypeArguments( + candidate.Member, receiverType, addMethodBinder.Compilation, ref useSiteInfo, out wasFullyInferred); + } + + if (constructed is null || !wasFullyInferred) + { + // It is quite possible that inference failed because we didn't supply type from the second argument + if (typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[1])) + { + // Let's attempt inference with type for the second parameter + // We are going to use the second parameter's type for that + var definition = candidate.Member; + var argumentRefKinds = ArrayBuilder.GetInstance(2, RefKind.None); + + OverloadResolution.GetEffectiveParameterTypes( + definition, + argumentCount: 2, + argToParamMap: default, + argumentRefKinds: argumentRefKinds, + isMethodGroupConversion: false, + allowRefOmittedArguments: methodGroup.ReceiverOpt.IsExpressionOfComImportType(), + binder: addMethodBinder, + expanded: candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm, + parameterTypes: out ImmutableArray parameterTypes, + parameterRefKinds: out ImmutableArray parameterRefKinds); + + argumentRefKinds.Free(); + + TypeSymbol secondArgumentType = candidate.Member.Parameters[1].Type; + + if (constructed?.TypeSubstitution is { } typeMap) + { + // If we were able to infer something just from the first parameter, + // apply that to the second type, otherwise inference is going to fail + // for those type parameters. + secondArgumentType = typeMap.SubstituteType(secondArgumentType).Type; + } + + MethodTypeInferenceResult inferenceResult = MethodTypeInferrer.Infer( + addMethodBinder, + addMethodBinder.Conversions, + definition.TypeParameters, + definition.ContainingType, + parameterTypes, + parameterRefKinds, + ImmutableArray.Create(methodGroup.ReceiverOpt, new BoundValuePlaceholder(syntax, secondArgumentType) { WasCompilerGenerated = true }), + ref useSiteInfo); + + if (!inferenceResult.Success) + { + continue; + } + + if (thisTypeIsOpen) + { + constructed = definition.Construct(inferenceResult.InferredTypeArguments); + } + } + else + { + continue; + } + } + + if (thisTypeIsOpen) + { + Debug.Assert(constructed is not null); + var conversions = constructed.ContainingAssembly.CorLibrary.TypeConversions; + var conversion = conversions.ConvertExtensionMethodThisArg(constructed.Parameters[0].Type, receiverType, ref useSiteInfo); + if (!conversion.Exists) + { + // PROTOTYPE: Test this code path + continue; // Conversion to 'this' parameter failed + } + } + } + else if (typeParameters.Any((typeParameter, parameter) => !parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[0])) + { + // A type parameter does not appear in the parameter type. + continue; + } + } + + resultBuilder.Add(candidate.Member); + } + + addMethods = resultBuilder.ToImmutableAndFree(); + return addMethods; + } + + // This is what CanEarlyBindSingleCandidateInvocationWithDynamicArgument is doing in terms of reporting diagnostics and detecting a failure + static bool canEarlyBindSingleCandidateInvocationWithDynamicArgument( + Binder addMethodBinder, + SyntaxNode syntax, + BoundMethodGroup boundMethodGroup, + BindingDiagnosticBag diagnostics, + MethodGroupResolution resolution, + MemberResolutionResult methodResolutionResult, + MethodSymbol singleCandidate) + { + Debug.Assert(boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty); + + if (singleCandidate.IsGenericMethod) + { + return false; + } + + if (addMethodBinder.IsAmbiguousDynamicParamsArgument(resolution.AnalyzedArguments.Arguments, methodResolutionResult, out SyntaxNode argumentSyntax)) + { + return false; + } + + return true; + } + // This is what TryEarlyBindSingleCandidateInvocationWithDynamicArgument is doing in terms of reporting diagnostics and detecting a failure static bool? tryEarlyBindSingleCandidateInvocationWithDynamicArgument( Binder addMethodBinder, @@ -1187,7 +1305,7 @@ static bool bindMethodGroupInvocation( out MethodSymbol? addMethod) { MethodSymbol singleCandidate = methodResolutionResult.LeastOverriddenMember; - if (!addMethodBinder.CanEarlyBindSingleCandidateInvocationWithDynamicArgument(syntax, boundMethodGroup, diagnostics, resolution, methodResolutionResult, singleCandidate)) + if (!canEarlyBindSingleCandidateInvocationWithDynamicArgument(addMethodBinder, syntax, boundMethodGroup, diagnostics, resolution, methodResolutionResult, singleCandidate)) { addMethod = null; return null; @@ -1285,122 +1403,6 @@ static bool bindInvocationExpressionContinued( } } - internal bool HasCollectionExpressionAddMethod(SyntaxNode syntax, TypeSymbol targetType) - { - const string methodName = "Add"; - var useSiteInfo = CompoundUseSiteInfo.Discarded; - - var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; - var memberAccess = BindInstanceMemberAccess( - syntax, - right: syntax, - boundLeft: implicitReceiver, - rightName: methodName, - rightArity: 0, - typeArgumentsSyntax: default, - typeArgumentsWithAnnotations: default, - invoked: true, - indexed: false, - BindingDiagnosticBag.Discarded); - if (memberAccess is not BoundMethodGroup methodGroup) - { - return false; - } - - Debug.Assert(methodGroup.SearchExtensionMethods); - - if (methodGroup.ResultKind == LookupResultKind.Viable && - methodGroup.Methods.Any(m => isApplicableAddMethod(m.GetConstructedLeastOverriddenMethod(accessingTypeOpt: null, requireSameReturnType: false), expectingExtensionMethod: false))) - { - return true; - } - - if (methodGroup.SearchExtensionMethods && - hasApplicableAddExtensionMethod(syntax, implicitReceiver)) - { - return true; - } - - return false; - - bool hasApplicableAddExtensionMethod(SyntaxNode syntax, BoundObjectOrCollectionValuePlaceholder implicitReceiver) - { - foreach (var scope in new ExtensionMethodScopes(this)) - { - var methodGroup = MethodGroup.GetInstance(); - PopulateExtensionMethodsFromSingleBinder(scope, methodGroup, syntax, implicitReceiver, rightName: methodName, typeArgumentsWithAnnotations: default, BindingDiagnosticBag.Discarded); - bool anyApplicable = methodGroup.Methods.Any(m => isApplicableAddMethod(m, expectingExtensionMethod: true)); - methodGroup.Free(); - if (anyApplicable) - { - return true; - } - } - return false; - } - - bool isApplicableAddMethod(MethodSymbol method, bool expectingExtensionMethod) - { - if (method.IsStatic != expectingExtensionMethod) - { - return false; - } - - var parameters = method.Parameters; - int valueIndex = expectingExtensionMethod ? 1 : 0; - int requiredLength = valueIndex + 1; - if (parameters.Length < requiredLength) - { - return false; - } - - // Any trailing parameters must be optional or params. - int optionalLength = parameters.Length - (OverloadResolution.IsValidParams(this, method) ? 1 : 0); - for (int i = requiredLength; i < optionalLength; i++) - { - if (parameters[i] is not ({ IsOptional: true, RefKind: RefKind.None or RefKind.In or RefKind.RefReadOnlyParameter })) - { - return false; - } - } - - // Extension method 'this' parameter must be by value, ref, in, or ref readonly. - if (expectingExtensionMethod) - { - if (parameters[0].RefKind is not (RefKind.None or RefKind.Ref or RefKind.In or RefKind.RefReadOnlyParameter)) - { - Debug.Assert(false); // We should have treated this method as unsupported. Add a corresponding test. - return false; - } - } - - // Value parameter must be by value, in, or ref readonly. - if (parameters[valueIndex].RefKind is not (RefKind.None or RefKind.In or RefKind.RefReadOnlyParameter)) - { - return false; - } - - // If the method is generic, fail if there are type arguments that are not referenced - // in the required parameters types. That is, fail if we know the type arguments cannot - // be inferred from the arguments. - var typeParameters = method.TypeParameters; - if (typeParameters.Length > 0) - { - var requiredParameters = parameters.AsSpan(0, requiredLength); - foreach (var typeParameter in typeParameters) - { - if (requiredParameters.All(typeParameter, (parameter, typeParameter) => !parameter.Type.ContainsTypeParameter(typeParameter))) - { - // The type parameter does not appear in any of the parameter types. - return false; - } - } - } - - return true; - } - } - /// /// If the element is from a collection type where elements are added with collection initializers, /// return the argument to the collection initializer Add method or null if the element is not a @@ -1558,7 +1560,7 @@ private void GenerateImplicitConversionErrorForCollectionExpression( } if (elements.Length > 0 && - !HasCollectionExpressionAddMethod(node.Syntax, targetType)) + !HasCollectionExpressionApplicableAddMethod(node.Syntax, targetType, addMethods: out _, diagnostics)) { Error(diagnostics, ErrorCode.ERR_CollectionExpressionMissingAdd_New, node.Syntax, targetType); reportedErrors = true; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 13d3755d950e0..0e7cb5dc95470 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -5933,7 +5933,7 @@ boundElementInitializerExpressions[0] is not var d = BindingDiagnosticBag.GetInstance(); // This assert provides some validation that, if the real invocation binding succeeds, then the HasCollectionExpressionApplicableAddMethod helper succeeds as well. - Debug.Assert(collectionInitializerAddMethodBinder.HasCollectionExpressionApplicableAddMethod(elementInitializer, implicitReceiver.Type, boundElementInitializerExpressions[0].Type, addMethods: out _, d)); + Debug.Assert(collectionInitializerAddMethodBinder.HasCollectionExpressionApplicableAddMethod(elementInitializer, implicitReceiver.Type, addMethods: out _, d)); d.Free(); } @@ -7915,18 +7915,12 @@ protected MethodGroupResolution BindExtensionMethod( bool withDependencies, in CallingConventionInfo callingConvention = default) { - // - // !!! ATTENTION !!! - // - // This function should be kept in sync with local function - // HasCollectionExpressionAddMethod.hasApplicableAddExtensionMethod. - // - Debug.Assert((options & ~(OverloadResolution.Options.IsMethodGroupConversion | OverloadResolution.Options.IsFunctionPointerResolution | OverloadResolution.Options.InferWithDynamic | OverloadResolution.Options.IgnoreNormalFormIfHasValidParamsParameter | - OverloadResolution.Options.DynamicResolution)) == 0); + OverloadResolution.Options.DynamicResolution | + OverloadResolution.Options.DynamicConvertsToAnything)) == 0); var firstResult = new MethodGroupResolution(); AnalyzedArguments actualArguments = null; @@ -9987,7 +9981,8 @@ private MethodGroupResolution ResolveDefaultMethodGroup( OverloadResolution.Options.IsFunctionPointerResolution | OverloadResolution.Options.InferWithDynamic | OverloadResolution.Options.IgnoreNormalFormIfHasValidParamsParameter | - OverloadResolution.Options.DynamicResolution)) == 0); + OverloadResolution.Options.DynamicResolution | + OverloadResolution.Options.DynamicConvertsToAnything)) == 0); var methods = node.Methods; if (methods.Length == 0) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index 366a0e05659ac..b2cb04125021b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -388,14 +388,6 @@ private BoundExpression BindDynamicInvocation( BindingDiagnosticBag diagnostics, CSharpSyntaxNode queryClause) { - // - // !!! ATTENTION !!! - // - // In terms of errors relevant for HasCollectionExpressionApplicableAddMethod check - // this function should be kept in sync with local function - // HasCollectionExpressionApplicableAddMethod.bindDynamicInvocation - // - CheckNamedArgumentsForDynamicInvocation(arguments, diagnostics); bool hasErrors = false; @@ -891,6 +883,14 @@ private bool CanEarlyBindSingleCandidateInvocationWithDynamicArgument( MemberResolutionResult methodResolutionResult, MethodSymbol singleCandidate) { + // + // !!! ATTENTION !!! + // + // In terms of errors relevant for HasCollectionExpressionApplicableAddMethod check + // this function should be kept in sync with local function + // HasCollectionExpressionApplicableAddMethod.canEarlyBindSingleCandidateInvocationWithDynamicArgument + // + if (boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty && singleCandidate.IsGenericMethod) { // If we call an unconstructed generic function with a diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index f80409e0c41bc..9cbb8ed1d6331 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -194,10 +194,12 @@ protected override Conversion GetCollectionExpressionConversion( } if (elements.Length > 0 && - !_binder.HasCollectionExpressionAddMethod(syntax, targetType)) + !_binder.HasCollectionExpressionApplicableAddMethod(syntax, targetType, addMethods: out _, BindingDiagnosticBag.Discarded)) { return Conversion.NoConversion; } + + // PROTOTYPE: Probably should at least accumulate dependencies and propagate them in case of success. } var builder = ArrayBuilder.GetInstance(elements.Length); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index d5b9a3efeb4ae..da03c69ff5f50 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -126,6 +126,7 @@ public enum Options : byte IsFunctionPointerResolution = 0b_00010000, IsExtensionMethodResolution = 0b_00100000, DynamicResolution = 0b_01000000, + DynamicConvertsToAnything = 0b_10000000, } // Perform overload resolution on the given method group, with the given arguments and @@ -870,6 +871,7 @@ private MemberAnalysisResult IsConstructorApplicableInNormalForm( hasAnyRefOmittedArgument: false, ignoreOpenTypes: false, completeResults: completeResults, + dynamicConvertsToAnything: false, useSiteInfo: ref useSiteInfo); } @@ -911,6 +913,7 @@ private MemberAnalysisResult IsConstructorApplicableInExpandedForm( hasAnyRefOmittedArgument: false, ignoreOpenTypes: false, completeResults: completeResults, + dynamicConvertsToAnything: false, useSiteInfo: ref useSiteInfo); Debug.Assert(!result.IsValid || result.Kind == MemberResolutionKind.ApplicableInExpandedForm); @@ -1063,6 +1066,7 @@ private void AddMemberToCandidateSet( arguments, allowRefOmittedArguments: (options & Options.AllowRefOmittedArguments) != 0, completeResults: completeResults, + dynamicConvertsToAnything: (options & Options.DynamicConvertsToAnything) != 0, useSiteInfo: ref useSiteInfo); if (PreferExpandedFormOverNormalForm(normalResult, expandedResult)) @@ -1210,7 +1214,7 @@ public static bool TryInferParamsCollectionIterationType(Binder binder, TypeSymb return false; } - if (!binder.HasCollectionExpressionApplicableAddMethod(syntax, type, elementType.Type, addMethods: out _, BindingDiagnosticBag.Discarded)) + if (!binder.HasCollectionExpressionApplicableAddMethod(syntax, type, addMethods: out _, BindingDiagnosticBag.Discarded)) { return false; } @@ -3702,6 +3706,7 @@ private MemberResolutionResult IsMemberApplicableInNormalForm( hasAnyRefOmittedArgument: hasAnyRefOmittedArgument, inferWithDynamic: (options & Options.InferWithDynamic) != 0, completeResults: completeResults, + dynamicConvertsToAnything: (options & Options.DynamicConvertsToAnything) != 0, useSiteInfo: ref useSiteInfo); // If we were producing complete results and had missing arguments, we pushed on in order to call IsApplicable for @@ -3721,6 +3726,7 @@ private MemberResolutionResult IsMemberApplicableInExpandedForm useSiteInfo) where TMember : Symbol { @@ -3763,6 +3769,7 @@ private MemberResolutionResult IsMemberApplicableInExpandedForm IsApplicable( bool hasAnyRefOmittedArgument, bool inferWithDynamic, bool completeResults, + bool dynamicConvertsToAnything, ref CompoundUseSiteInfo useSiteInfo) where TMember : Symbol { @@ -3898,6 +3906,7 @@ private MemberResolutionResult IsApplicable( hasAnyRefOmittedArgument: hasAnyRefOmittedArgument, ignoreOpenTypes: ignoreOpenTypes, completeResults: completeResults, + dynamicConvertsToAnything: dynamicConvertsToAnything, useSiteInfo: ref useSiteInfo); return new MemberResolutionResult(member, leastOverriddenMember, applicableResult, hasTypeArgumentsInferredFromFunctionType); } @@ -3967,6 +3976,7 @@ private MemberAnalysisResult IsApplicable( bool hasAnyRefOmittedArgument, bool ignoreOpenTypes, bool completeResults, + bool dynamicConvertsToAnything, ref CompoundUseSiteInfo useSiteInfo) { TypeWithAnnotations paramsElementTypeOpt; @@ -4079,9 +4089,15 @@ private MemberAnalysisResult IsApplicable( ignoreOpenTypes, ref useSiteInfo, forExtensionMethodThisArg, - hasInterpolatedStringRefMismatch); + hasInterpolatedStringRefMismatch, + dynamicConvertsToAnything); - if (forExtensionMethodThisArg && !Conversions.IsValidExtensionMethodThisArgConversion(conversion)) + Debug.Assert( + !forExtensionMethodThisArg || + (!conversion.IsDynamic || + (ignoreOpenTypes && parameters.ParameterTypes[argumentPosition].Type.ContainsTypeParameter(parameterContainer: (MethodSymbol)candidate)))); + + if (forExtensionMethodThisArg && !conversion.IsDynamic && !Conversions.IsValidExtensionMethodThisArgConversion(conversion)) { // Return early, without checking conversions of subsequent arguments, // if the instance argument is not convertible to the 'this' parameter, @@ -4150,7 +4166,8 @@ private Conversion CheckArgumentForApplicability( bool ignoreOpenTypes, ref CompoundUseSiteInfo useSiteInfo, bool forExtensionMethodThisArg, - bool hasInterpolatedStringRefMismatch) + bool hasInterpolatedStringRefMismatch, + bool dynamicConvertsToAnything) { // Spec 7.5.3.1 // For each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is identical @@ -4191,7 +4208,9 @@ private Conversion CheckArgumentForApplicability( { var conversion = forExtensionMethodThisArg ? Conversions.ClassifyImplicitExtensionMethodThisArgConversion(argument, argument.Type, parameterType, ref useSiteInfo) : - Conversions.ClassifyImplicitConversionFromExpression(argument, parameterType, ref useSiteInfo); + ((!dynamicConvertsToAnything || !argument.Type.IsDynamic()) ? + Conversions.ClassifyImplicitConversionFromExpression(argument, parameterType, ref useSiteInfo) : + Conversion.ImplicitDynamic); Debug.Assert((!conversion.Exists) || conversion.IsImplicit, "ClassifyImplicitConversion should only return implicit conversions"); if (hasInterpolatedStringRefMismatch && !conversion.IsInterpolatedStringHandler) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs index 188d1893ffebb..d2955a4ebf97e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs @@ -505,23 +505,14 @@ internal void ReportDiagnostics( // but no argument was supplied for it then the first such method is // the best bad method. case MemberResolutionKind.RequiredParameterMissing: - if ((binder.Flags & BinderFlags.CollectionExpressionConversionValidation) != 0) + if ((binder.Flags & BinderFlags.CollectionExpressionConversionValidation) != 0 && receiver is null) { - if (receiver is null) - { - Debug.Assert(firstSupported.Member is MethodSymbol { MethodKind: MethodKind.Constructor }); - diagnostics.Add( - isParamsModifierValidation ? - ErrorCode.ERR_ParamsCollectionMissingConstructor : - ErrorCode.ERR_CollectionExpressionMissingConstructor, - location); - } - else - { - Debug.Assert(firstSupported.Member is MethodSymbol { Name: "Add" }); - int argumentOffset = arguments.IsExtensionMethodInvocation ? 1 : 0; - diagnostics.Add(ErrorCode.ERR_CollectionExpressionMissingAdd, location, arguments.Arguments[argumentOffset].Type, firstSupported.Member); - } + Debug.Assert(firstSupported.Member is MethodSymbol { MethodKind: MethodKind.Constructor }); + diagnostics.Add( + isParamsModifierValidation ? + ErrorCode.ERR_ParamsCollectionMissingConstructor : + ErrorCode.ERR_CollectionExpressionMissingConstructor, + location); } else { @@ -1127,12 +1118,7 @@ private bool HadBadArguments( } } - if (flags.Includes(BinderFlags.CollectionExpressionConversionValidation)) - { - Debug.Assert(arguments.Arguments.Count == argumentOffset + 1); - diagnostics.Add(ErrorCode.ERR_CollectionExpressionMissingAdd, location, arguments.Arguments[argumentOffset].Type, method); - } - else + if (!flags.Includes(BinderFlags.CollectionExpressionConversionValidation)) { // The best overloaded Add method '{0}' for the collection initializer has some invalid arguments diagnostics.Add(ErrorCode.ERR_BadArgTypesForCollectionAdd, location, symbols, method); diff --git a/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs index 4d7e123e1468d..d5f5bcbe61e54 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ReducedExtensionMethodSymbol.cs @@ -109,10 +109,12 @@ private ReducedExtensionMethodSymbol(MethodSymbol reducedFrom) /// are not satisfied, the return value is null. /// /// Compilation used to check constraints. The latest language version is assumed if this is null. - private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, CSharpCompilation compilation, + internal static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, CSharpCompilation compilation, ref CompoundUseSiteInfo useSiteInfo, out bool wasFullyInferred) { Debug.Assert(method.IsExtensionMethod); + Debug.Assert(method.MethodKind != MethodKind.ReducedExtension); + Debug.Assert(method.ParameterCount > 0); Debug.Assert((object)thisType != null); if (!method.IsGenericMethod || method != method.ConstructedFrom) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 85eba6bdf14bb..e52b792c6318c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -1579,8 +1579,10 @@ void validateParamsType(BindingDiagnosticBag diagnostics) checkIsAtLeastAsVisible(syntax, binder, constructor, diagnostics); } - if (!binder.HasCollectionExpressionApplicableAddMethod(syntax, Type, elementType, out ImmutableArray addMethods, diagnostics)) + if (!binder.HasCollectionExpressionApplicableAddMethod(syntax, Type, out ImmutableArray addMethods, diagnostics)) { + // PROTOTYPE: Report ERR_CollectionExpressionMissingAdd_New or similar if there are no errors in the bag + // Probably shouldn't happen, but better safe than sorry. return; } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index a1708506bb715..942eff47bbc0f 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -4506,12 +4506,18 @@ static void Main() // (7,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [default]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(7, 13), + // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = [default]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(7, 13), // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [default]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(7, 13), // (8,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [null]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(8, 13), + // (8,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = [null]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(8, 13), // (8,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(8, 13), @@ -4521,12 +4527,18 @@ static void Main() // (9,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = ['a']; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(9, 13), + // (9,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = ['a']; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(9, 13), // (9,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(9, 13), // (10,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [1]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(10, 13), + // (10,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = [1]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(10, 13), // (10,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(10, 13), @@ -4536,6 +4548,9 @@ static void Main() // (11,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [..""]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"[..""""]").WithArguments("string", "0").WithLocation(11, 13), + // (11,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = [..""]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(11, 13), // (11,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [..""]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(11, 13)); @@ -4561,48 +4576,63 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)[]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(5, 21), - // (6,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)[default]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(6, 21), - // (6,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. - // _ = (string)[default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(6, 21), - // (6,22): error CS8716: There is no target type for the default literal. - // _ = (string)[default]; - Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(6, 22), - // (7,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)[null]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(7, 21), - // (7,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. - // _ = (string)[null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(7, 21), - // (7,22): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type - // _ = (string)[null]; - Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(7, 22), - // (8,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)['a']; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(8, 21), - // (8,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. - // _ = (string)['a']; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(8, 21), - // (9,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)[1]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(9, 21), - // (9,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. - // _ = (string)[1]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(9, 21), - // (9,22): error CS0029: Cannot implicitly convert type 'int' to 'char' - // _ = (string)[1]; - Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(9, 22), - // (10,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // _ = (string)[..""]; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"[..""""]").WithArguments("string", "0").WithLocation(10, 21), - // (10,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. - // _ = (string)[..""]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(10, 21)); + // (5,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)[]; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(5, 21), + // (6,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)[default]; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(6, 21), + // (6,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // _ = (string)[default]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(6, 21), + // (6,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // _ = (string)[default]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(6, 21), + // (6,22): error CS8716: There is no target type for the default literal. + // _ = (string)[default]; + Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(6, 22), + // (7,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)[null]; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(7, 21), + // (7,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // _ = (string)[null]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(7, 21), + // (7,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // _ = (string)[null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(7, 21), + // (7,22): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type + // _ = (string)[null]; + Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(7, 22), + // (8,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)['a']; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(8, 21), + // (8,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // _ = (string)['a']; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(8, 21), + // (8,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // _ = (string)['a']; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(8, 21), + // (9,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)[1]; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(9, 21), + // (9,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // _ = (string)[1]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(9, 21), + // (9,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // _ = (string)[1]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(9, 21), + // (9,22): error CS0029: Cannot implicitly convert type 'int' to 'char' + // _ = (string)[1]; + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(9, 22), + // (10,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // _ = (string)[..""]; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, @"[..""""]").WithArguments("string", "0").WithLocation(10, 21), + // (10,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // _ = (string)[..""]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(10, 21), + // (10,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // _ = (string)[..""]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(10, 21)); } [Fact] @@ -5288,6 +5318,9 @@ struct S : IEnumerable """; var comp = CreateCompilation(new[] { sourceA, sourceB2 }); comp.VerifyEmitDiagnostics( + // 1.cs(2,5): error CS1061: 'S' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'S' could be found (are you missing a using directive or an assembly reference?) + // s = [1, 2]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2]").WithArguments("S", "Add").WithLocation(2, 5), // 1.cs(2,5): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2]").WithArguments("S").WithLocation(2, 5), @@ -5809,6 +5842,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (13,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "S.Add(int, int)").WithLocation(13, 13), // (13,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(13, 13)); @@ -5838,6 +5874,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (15,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "S.Add(int, int)").WithLocation(15, 13), // (15,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(15, 13)); @@ -5870,6 +5909,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (18,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'Extensions.Add(S, T, T)' + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "Extensions.Add(S, T, T)").WithLocation(18, 13), // (18,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(18, 13)); @@ -6189,6 +6231,9 @@ static void Main() // (7,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = ['a']; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(7, 13), + // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) + // s = ['a']; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(7, 13), // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(7, 13)); @@ -6369,6 +6414,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (16,31): error CS0122: 'MyCollection.Add(int)' is inaccessible due to its protection level + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_BadAccess, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(16, 31), // (16,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(16, 31)); @@ -6407,6 +6455,9 @@ static void Main() """; comp = CreateCompilation(sourceB, references: new[] { refA }); comp.VerifyEmitDiagnostics( + // (6,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, ..x]").WithArguments("MyCollection", "Add").WithLocation(6, 31), // (6,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(6, 31)); @@ -6468,6 +6519,9 @@ static void Main() // (13,42): error CS1954: The best overloaded method match 'MyCollection.Add(out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyCollection.Add(out object)").WithLocation(13, 42), + // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(out object)").WithLocation(15, 34), // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); @@ -6500,6 +6554,9 @@ static void Main() // (13,42): error CS1954: The best overloaded method match 'MyCollection.Add(ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyCollection.Add(ref object)").WithLocation(13, 42), + // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(ref object)").WithLocation(15, 34), // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); @@ -6639,6 +6696,9 @@ static void Main() // (16,42): error CS0411: The type arguments for method 'Extensions.Add(ref MyCollection, out T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "1").WithArguments("Extensions.Add(ref MyCollection, out T)").WithLocation(16, 42), + // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, out T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, out T)").WithLocation(18, 34), // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); @@ -6674,6 +6734,9 @@ static void Main() // (16,42): error CS0411: The type arguments for method 'Extensions.Add(ref MyCollection, ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // MyCollection x = new() { 1 }; Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "1").WithArguments("Extensions.Add(ref MyCollection, ref T)").WithLocation(16, 42), + // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, ref T)").WithLocation(18, 34), // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); @@ -6822,12 +6885,18 @@ static void Main() // (17,21): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // x = new() { "1" }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, @"""1""").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(17, 21), + // (18,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // x = ["2"]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, @"[""2""]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(18, 13), // (18,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // x = ["2"]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[""2""]").WithArguments("MyCollection").WithLocation(18, 13), // (20,21): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // y = new() { 3 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "3").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(20, 21), + // (21,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // y = [4]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[4]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(21, 13), // (21,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // y = [4]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[4]").WithArguments("MyCollection").WithLocation(21, 13)); @@ -6856,6 +6925,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (14,31): error CS1921: The best overloaded method match for 'MyCollection.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(14, 31), // (14,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(14, 31)); @@ -7992,10 +8064,10 @@ static void Main() Diagnostic(ErrorCode.ERR_NoTypeDef, "[1, 2]").WithArguments("A1", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 13), // 0.cs(13,14): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // y = [3, 4]; - Diagnostic(ErrorCode.ERR_NoTypeDef, "3").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 14), - // 0.cs(13,17): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + Diagnostic(ErrorCode.ERR_NoTypeDef, "[3, 4]").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 13), + // 0.cs(13,13): error CS9230: Collection expression type 'B2' must have an instance or extension method 'Add' that can be called with a single argument. // y = [3, 4]; - Diagnostic(ErrorCode.ERR_NoTypeDef, "4").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 17)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[3, 4]").WithArguments("B2").WithLocation(13, 13)); } [Fact] @@ -8094,9 +8166,15 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (7,13): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(int, int)' + // d = [default]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[default]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(7, 13), // (7,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [default]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(7, 13), + // (8,13): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(int, int)' + // d = [new KeyValuePair(1, 2)]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[new KeyValuePair(1, 2)]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(8, 13), // (8,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [new KeyValuePair(1, 2)]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(8, 13), @@ -15042,6 +15120,9 @@ static void Main() // (6,24): error CS0416: 'T': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(T), "ToString")] Diagnostic(ErrorCode.ERR_AttrArgWithTypeVars, "typeof(T)").WithArguments("T").WithLocation(6, 24), + // (19,44): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) + // Container.MyCollection y = [null]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("Container.MyCollection", "Add").WithLocation(19, 44), // (19,44): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("Container.MyCollection").WithLocation(19, 44), @@ -15555,6 +15636,9 @@ static void Main() // (7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] Diagnostic(ErrorCode.ERR_AttrArgWithTypeVars, "typeof(MyCollectionBuilder)").WithArguments("Container.MyCollectionBuilder").WithLocation(7, 24), + // (27,41): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) + // Container.MyCollection y = [default]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("Container.MyCollection", "Add").WithLocation(27, 41), // (27,41): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [default]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("Container.MyCollection").WithLocation(27, 41)); @@ -16337,6 +16421,9 @@ static void Main() """; comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( + // (6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection y = [2]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[2]").WithArguments("MyCollection", "Add").WithLocation(6, 26), // (6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [2]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[2]").WithArguments("MyCollection").WithLocation(6, 26)); @@ -16455,6 +16542,9 @@ static void Main() // 1.cs(6,26): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection y = [1, 2, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1, 2, 3]").WithLocation(6, 26), + // 1.cs(6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection y = [1, 2, 3]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, 3]").WithArguments("MyCollection", "Add").WithLocation(6, 26), // 1.cs(6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, 3]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, 3]").WithArguments("MyCollection").WithLocation(6, 26)); @@ -16526,6 +16616,9 @@ static void Main() // 1.cs(6,34): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection y = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1, 2, null]").WithLocation(6, 34), + // 1.cs(6,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection y = [1, 2, null]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, null]").WithArguments("MyCollection", "Add").WithLocation(6, 34), // 1.cs(6,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, null]").WithArguments("MyCollection").WithLocation(6, 34)); @@ -25081,6 +25174,11 @@ .. GetConfig(), var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (4,52): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(string, object)' + // Dictionary Config => /**/[ + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, @"[ + .. GetConfig(), + ]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(string, object)").WithLocation(4, 52), // (4,52): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // Dictionary Config => /**/[ Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[ @@ -34745,6 +34843,9 @@ static void Main() """; var comp = CreateCompilation([sourceA, sourceB1]); comp.VerifyEmitDiagnostics( + // (7,34): error CS0122: 'MyCollection.Add(int)' is inaccessible due to its protection level + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadAccess, "[x, ..y]").WithArguments("MyCollection.Add(int)").WithLocation(7, 34), // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); @@ -34809,6 +34910,9 @@ static void Main() comp = CreateCompilation([sourceB, s_collectionExtensions], references: [refA]); comp.VerifyEmitDiagnostics( + // (7,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 34), // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); @@ -34855,6 +34959,9 @@ static void Main() var comp = CreateCompilation([sourceA, sourceC, s_collectionExtensions]); comp.VerifyEmitDiagnostics( + // (7,34): error CS0122: 'MyCollectionBase.Add(object)' is inaccessible due to its protection level + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadAccess, "[x, ..y]").WithArguments("MyCollectionBase.Add(object)").WithLocation(7, 34), // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); @@ -34986,6 +35093,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (15,32): error CS1954: The best overloaded method match 'MyCollection.Add(ref int?)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[x, ..y, null]").WithArguments("MyCollection.Add(" + refKind + " int?)").WithLocation(15, 32), // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); @@ -35095,6 +35205,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (19,32): error CS1954: The best overloaded method match 'Extensions.Add(MyCollection, ref T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[x, ..y, null]").WithArguments("Extensions.Add(MyCollection, " + refKind + " T)").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); @@ -35350,6 +35463,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (15,32): error CS1501: No overload for method 'Add' takes 1 arguments + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgCount, "[x, ..y, null]").WithArguments("Add", "1").WithLocation(15, 32), // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); @@ -35413,12 +35529,12 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (19,33): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 33), - // (19,38): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 32), + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "y").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 38), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(20, 40)); @@ -35452,16 +35568,13 @@ static void Main() } """; var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. - // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32)); + comp.VerifyEmitDiagnostics(); } [Theory] [InlineData("")] - [InlineData("in")] - [InlineData("ref readonly")] + [InlineData("in ")] + [InlineData("ref readonly ")] public void AddMethod_03A(string refKind) { string source = $$""" @@ -35484,12 +35597,15 @@ static void Main() } """; var comp = CreateCompilation(source); - if (refKind == "ref readonly") + if (refKind == "ref readonly ") { comp.VerifyEmitDiagnostics( - // (7,67): 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 void Add(T t, ref readonly int x, ref readonly int y = 2) { _list.Add(t); } - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "2").WithArguments("y").WithLocation(7, 67), + // (7,69): 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 void Add(T t, ref readonly int x, ref readonly int y = 2) { _list.Add(t); } + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "2").WithArguments("y").WithLocation(7, 69), + // (15,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, ref readonly int, ref readonly int)' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "MyCollection.Add(int?, ref readonly int, ref readonly int)").WithLocation(15, 32), // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); @@ -35497,6 +35613,9 @@ static void Main() else { comp.VerifyEmitDiagnostics( + // (15,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int, int)' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "MyCollection.Add(int?, " + refKind + "int, " + refKind + "int)").WithLocation(15, 32), // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); @@ -35547,6 +35666,9 @@ static void Main() """; var comp = CreateCompilation(sourceB, references: [refA]); comp.VerifyEmitDiagnostics( + // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'index' of 'MyCollection.Add(int, ref int)' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("index", "MyCollection.Add(int, " + (useOut ? "out" : "ref") + " int)").WithLocation(7, 31), // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); @@ -35710,6 +35832,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?[])' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("y", "MyCollection.Add(int?, int?[])").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); @@ -35744,12 +35869,12 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (19,33): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 33), - // (19,38): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 32), + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "y").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 38), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(20, 40)); @@ -35784,6 +35909,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'z' of 'MyCollection.Add(int?, int?, int?[])' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("z", "MyCollection.Add(int?, int?, int?[])").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), @@ -35951,6 +36079,9 @@ static void Main() """; var comp = CreateCompilation(sourceB, references: [refA]); comp.VerifyEmitDiagnostics( + // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int, params int)' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(int, params int)").WithLocation(7, 31), // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); @@ -36073,6 +36204,9 @@ static void Main() """; var comp = CreateCompilation(sourceB, references: [refA]); comp.VerifyEmitDiagnostics( + // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(object, params object)' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(object, params object)").WithLocation(7, 31), // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); @@ -36106,6 +36240,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( + // (19,32): error CS1501: No overload for method 'Add' takes 1 arguments + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_BadArgCount, "[x, ..y, null]").WithArguments("Add", "1").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); @@ -36180,6 +36317,19 @@ static void Main() // (11,110): 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 void Add(this MyCollection collection, T t, ref readonly int x, ref readonly int y = 2) { collection.__AddInternal(t); } Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "2").WithArguments("y").WithLocation(11, 110), + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, ref readonly int, ref readonly int)' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, ref readonly int, ref readonly int)").WithLocation(19, 32), + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + } + else if (refKind == "in") + { + comp.VerifyEmitDiagnostics( + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, in int, in int)' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, in int, in int)").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); @@ -36187,6 +36337,9 @@ static void Main() else { comp.VerifyEmitDiagnostics( + // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, int, int)' + // MyCollection z = [x, ..y, null]; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, int, int)").WithLocation(19, 32), // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); @@ -36465,11 +36618,96 @@ static void Main() """; var comp = CreateCompilation(sourceB, references: [refA]); comp.VerifyEmitDiagnostics( + // (7,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 31), // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); } + [Fact] + public void AddMethod_Extension_10_WrongThisType() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this string collection, int x) => throw null; + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS1929: 'MyCollection' does not contain a definition for 'Add' and the best extension method overload 'Extensions.Add(string, int)' requires a receiver of type 'string' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadInstanceArgType, "[x, ..y]").WithArguments("MyCollection", "Add", "Extensions.Add(string, int)", "string").WithLocation(19, 32), + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + // (20,32): error CS1929: 'MyCollection' does not contain a definition for 'Add' and the best extension method overload 'Extensions.Add(string, int)' requires a receiver of type 'string' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_BadInstanceArgType, "new() { x }").WithArguments("MyCollection", "Add", "Extensions.Add(string, int)", "string").WithLocation(20, 32), + // (20,40): error CS1950: The best overloaded Add method 'Extensions.Add(string, int)' for the collection initializer has some invalid arguments + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions.Add(string, int)").WithLocation(20, 40) + ); + } + + [Fact] + public void AddMethod_Extension_11_WrongThisType() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this IEnumerable collection, int x) => throw null; + } + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + // (20,40): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("MyCollection", "Add").WithLocation(20, 40) + ); + } + [Fact] public void AddMethod_Base() { @@ -36576,6 +36814,9 @@ public static void Add(this {{(structOrClass == "struct" ? "ref" : "")}} T var comp = CreateCompilation([sourceA, sourceB, s_collectionExtensions]); comp.VerifyEmitDiagnostics( + // (7,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 34), // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); @@ -36619,6 +36860,9 @@ static class Extensions var comp = CreateCompilation([sourceA, sourceB, s_collectionExtensions]); comp.VerifyEmitDiagnostics( + // (7,34): error CS1921: The best overloaded method match for 'MyCollection.Add(object)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "[x, ..y]").WithArguments("MyCollection.Add(object)").WithLocation(7, 34), // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); @@ -37311,6 +37555,9 @@ static void Main() comp = CreateCompilation([sourceC, s_collectionExtensions], references: [refB]); comp.VerifyEmitDiagnostics( + // (7,35): error CS0012: The type 'MyCollectionA<>' is defined in an assembly that is not referenced. You must add a reference to assembly '41f5b758-1e64-4c10-88d8-6dd8029c374c, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // MyCollectionB z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoTypeDef, "[x, ..y]").WithArguments("MyCollectionA<>", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 35), // (7,35): error CS9230: Collection expression type 'MyCollectionB' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollectionB z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollectionB").WithLocation(7, 35)); @@ -38014,5 +38261,8 @@ static void Test(MyCollection a) Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[1]").WithArguments("Create", "long", "MyCollection").WithLocation(5, 14) ); } + + // PROTOTYPE: Can we extend 'dynamic' type? + // If so, test an 'Add' method like that. } } From d8bbb8ae3af1f5312c130f1087b1bac327e37003 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 26 Mar 2024 23:46:01 -0700 Subject: [PATCH 10/18] PR feedback --- .../Portable/Binder/Binder_Conversions.cs | 108 ++++++++---------- .../Semantics/CollectionExpressionTests.cs | 47 ++++++++ 2 files changed, 94 insertions(+), 61 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 53fbb46a5c233..03e43e4e08987 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1127,7 +1127,7 @@ static bool bindMethodGroupInvocation( { Debug.Assert(finalApplicableCandidates.Length > 0); - addMethods = filterOutBadGenericMethods(addMethodBinder, syntax, methodGroup, resolution, finalApplicableCandidates, ref useSiteInfo); + addMethods = filterOutBadGenericMethods(addMethodBinder, syntax, methodGroup, analyzedArguments, resolution, finalApplicableCandidates, ref useSiteInfo); result = !addMethods.IsEmpty; } } @@ -1151,18 +1151,17 @@ static bool bindMethodGroupInvocation( } static ImmutableArray filterOutBadGenericMethods( - Binder addMethodBinder, SyntaxNode syntax, BoundMethodGroup methodGroup, MethodGroupResolution resolution, + Binder addMethodBinder, SyntaxNode syntax, BoundMethodGroup methodGroup, AnalyzedArguments analyzedArguments, MethodGroupResolution resolution, ImmutableArray> finalApplicableCandidates, ref CompoundUseSiteInfo useSiteInfo) { Debug.Assert(methodGroup.ReceiverOpt is not null); - - ImmutableArray addMethods; var resultBuilder = ArrayBuilder.GetInstance(finalApplicableCandidates.Length); foreach (var candidate in finalApplicableCandidates) { // If the method is generic, skip it if the type arguments cannot be inferred. - var typeParameters = candidate.Member.TypeParameters; + var member = candidate.Member; + var typeParameters = member.TypeParameters; if (!typeParameters.IsEmpty) { @@ -1172,74 +1171,62 @@ static ImmutableArray filterOutBadGenericMethods( // Overload resolution doesn't check the conversion when 'this' type refers to a type parameter TypeSymbol? receiverType = methodGroup.ReceiverOpt.Type; Debug.Assert(receiverType is not null); - bool thisTypeIsOpen = typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[0]); + bool thisTypeIsOpen = typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), member.Parameters[0]); MethodSymbol? constructed = null; bool wasFullyInferred = false; if (thisTypeIsOpen) { constructed = ReducedExtensionMethodSymbol.InferExtensionMethodTypeArguments( - candidate.Member, receiverType, addMethodBinder.Compilation, ref useSiteInfo, out wasFullyInferred); + member, receiverType, addMethodBinder.Compilation, ref useSiteInfo, out wasFullyInferred); } if (constructed is null || !wasFullyInferred) { // It is quite possible that inference failed because we didn't supply type from the second argument - if (typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[1])) + if (!typeParameters.Any((typeParameter, parameter) => parameter.Type.ContainsTypeParameter(typeParameter), member.Parameters[1])) { - // Let's attempt inference with type for the second parameter - // We are going to use the second parameter's type for that - var definition = candidate.Member; - var argumentRefKinds = ArrayBuilder.GetInstance(2, RefKind.None); - - OverloadResolution.GetEffectiveParameterTypes( - definition, - argumentCount: 2, - argToParamMap: default, - argumentRefKinds: argumentRefKinds, - isMethodGroupConversion: false, - allowRefOmittedArguments: methodGroup.ReceiverOpt.IsExpressionOfComImportType(), - binder: addMethodBinder, - expanded: candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm, - parameterTypes: out ImmutableArray parameterTypes, - parameterRefKinds: out ImmutableArray parameterRefKinds); - - argumentRefKinds.Free(); - - TypeSymbol secondArgumentType = candidate.Member.Parameters[1].Type; - - if (constructed?.TypeSubstitution is { } typeMap) - { - // If we were able to infer something just from the first parameter, - // apply that to the second type, otherwise inference is going to fail - // for those type parameters. - secondArgumentType = typeMap.SubstituteType(secondArgumentType).Type; - } - - MethodTypeInferenceResult inferenceResult = MethodTypeInferrer.Infer( - addMethodBinder, - addMethodBinder.Conversions, - definition.TypeParameters, - definition.ContainingType, - parameterTypes, - parameterRefKinds, - ImmutableArray.Create(methodGroup.ReceiverOpt, new BoundValuePlaceholder(syntax, secondArgumentType) { WasCompilerGenerated = true }), - ref useSiteInfo); - - if (!inferenceResult.Success) - { - continue; - } - - if (thisTypeIsOpen) - { - constructed = definition.Construct(inferenceResult.InferredTypeArguments); - } + continue; } - else + + // Let's attempt inference with type for the second parameter + // We are going to use the second parameter's type for that + OverloadResolution.GetEffectiveParameterTypes( + member, + argumentCount: 2, + argToParamMap: default, + argumentRefKinds: analyzedArguments.RefKinds, + isMethodGroupConversion: false, + allowRefOmittedArguments: methodGroup.ReceiverOpt.IsExpressionOfComImportType(), // PROTOTYPE: Test effect of this flag + binder: addMethodBinder, + expanded: candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm, + parameterTypes: out ImmutableArray parameterTypes, + parameterRefKinds: out ImmutableArray parameterRefKinds); + + // If we were able to infer something just from the first parameter, + // use partially substituted second type, otherwise inference might fail + // for type parameters "shared" between the parameters. + TypeSymbol secondArgumentType = (constructed ?? member).Parameters[1].Type; + + MethodTypeInferenceResult inferenceResult = MethodTypeInferrer.Infer( + addMethodBinder, + addMethodBinder.Conversions, + member.TypeParameters, + member.ContainingType, + parameterTypes, + parameterRefKinds, + ImmutableArray.Create(methodGroup.ReceiverOpt, new BoundValuePlaceholder(syntax, secondArgumentType) { WasCompilerGenerated = true }), + ref useSiteInfo); + + if (!inferenceResult.Success) { continue; } + + if (thisTypeIsOpen) + { + constructed = member.Construct(inferenceResult.InferredTypeArguments); + } } if (thisTypeIsOpen) @@ -1254,18 +1241,17 @@ static ImmutableArray filterOutBadGenericMethods( } } } - else if (typeParameters.Any((typeParameter, parameter) => !parameter.Type.ContainsTypeParameter(typeParameter), candidate.Member.Parameters[0])) + else if (typeParameters.Any((typeParameter, parameter) => !parameter.Type.ContainsTypeParameter(typeParameter), member.Parameters[0])) { // A type parameter does not appear in the parameter type. continue; } } - resultBuilder.Add(candidate.Member); + resultBuilder.Add(member); } - addMethods = resultBuilder.ToImmutableAndFree(); - return addMethods; + return resultBuilder.ToImmutableAndFree(); } // This is what CanEarlyBindSingleCandidateInvocationWithDynamicArgument is doing in terms of reporting diagnostics and detecting a failure diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 942eff47bbc0f..57d1e7c3621ff 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -36708,6 +36708,53 @@ static void Main() ); } + [Fact] + public void AddMethod_Extension_12_ConstraintsViolated() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, params T[] args) + where T : struct + { + if (args is null) return; + foreach (var a in args) + collection.__AddInternal(a); + } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + MyCollection w = new() { x }; + } + } + """; + CreateCompilation([sourceA, sourceB1, s_collectionExtensions]).VerifyDiagnostics( + // (7,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 32), + // (9,40): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Extensions.Add(MyCollection, params T[])' + // MyCollection w = new() { x }; + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("Extensions.Add(MyCollection, params T[])", "T", "int?").WithLocation(9, 40) + ); + } + [Fact] public void AddMethod_Base() { From 52ab50188690ccf1b99a2ef012a5825a805d9cdf Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 07:05:18 -0700 Subject: [PATCH 11/18] Update tests after merge --- .../Test/Emit2/Semantics/CollectionExpressionTests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 9e2a472882c09..8cafd8399817e 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -25725,6 +25725,9 @@ static MyCollection Create(int x, int[] y) """; var comp = CreateCompilation([sourceB, sourceA]); comp.VerifyEmitDiagnostics( + // (5,26): error CS0118: 'Add' is a field but is used like a method + // return /**/[x, ..y]/**/; + Diagnostic(ErrorCode.ERR_BadSKknown, "[x, ..y]").WithArguments("Add", "field", "method").WithLocation(5, 26), // (5,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // return /**/[x, ..y]/**/; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(5, 26)); @@ -36787,6 +36790,9 @@ static void Main() // (12,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'Add' must be a concrete (non-generic) value type. // public static void Add(this in MyCollection collection, T t) { collection.__AddInternal(t); } Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "Add").WithArguments("Add").WithLocation(12, 24), + // (20,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(20, 31), // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); @@ -36796,6 +36802,9 @@ static void Main() // (12,24): error CS8337: The first parameter of a 'ref' extension method 'Add' must be a value type or a generic type constrained to struct. // public static void Add(this ref MyCollection collection, T t) { collection.__AddInternal(t); } Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "Add").WithArguments("Add").WithLocation(12, 24), + // (20,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(20, 31), // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); From 837dc731e8b5cd0bc1e146a0b140cda21b5f84a7 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 07:11:51 -0700 Subject: [PATCH 12/18] Replace existing error --- .../Portable/Binder/Binder_Conversions.cs | 2 +- .../CSharp/Portable/CSharpResources.resx | 3 - .../CSharp/Portable/Errors/ErrorCode.cs | 1 - .../CSharp/Portable/Errors/ErrorFacts.cs | 1 - .../Source/SourceComplexParameterSymbol.cs | 2 +- .../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 - .../Semantics/CollectionExpressionTests.cs | 260 +++++++++--------- 19 files changed, 132 insertions(+), 202 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 7b13bc6d0ccb1..7b642b77c002d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1551,7 +1551,7 @@ private void GenerateImplicitConversionErrorForCollectionExpression( if (elements.Length > 0 && !HasCollectionExpressionApplicableAddMethod(node.Syntax, targetType, addMethods: out _, diagnostics)) { - Error(diagnostics, ErrorCode.ERR_CollectionExpressionMissingAdd_New, node.Syntax, targetType); + Error(diagnostics, ErrorCode.ERR_CollectionExpressionMissingAdd, node.Syntax, targetType); reportedErrors = true; } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index aa2a28d28aad8..fb6705753cfd4 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6863,9 +6863,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Collection expression type must have an applicable constructor that can be called with no arguments. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index dec96cc921739..70c3ed6d8b861 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2301,7 +2301,6 @@ internal enum ErrorCode ERR_ParamsCollectionMissingConstructor = 9228, ERR_NoModifiersOnUsing = 9229, - ERR_CollectionExpressionMissingAdd_New = 9230, // PROTOTYPE: Replace ERR_CollectionExpressionMissingAdd. #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index fdfc3b57c4140..b4eaef25f8e7a 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2431,7 +2431,6 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_ParamsCollectionExtensionAddMethod: case ErrorCode.ERR_ParamsCollectionMissingConstructor: case ErrorCode.ERR_NoModifiersOnUsing: - case ErrorCode.ERR_CollectionExpressionMissingAdd_New: return false; default: // NOTE: All error codes must be explicitly handled in this switch statement diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index e52b792c6318c..ce9fbb3e028c6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -1581,7 +1581,7 @@ void validateParamsType(BindingDiagnosticBag diagnostics) if (!binder.HasCollectionExpressionApplicableAddMethod(syntax, Type, out ImmutableArray addMethods, diagnostics)) { - // PROTOTYPE: Report ERR_CollectionExpressionMissingAdd_New or similar if there are no errors in the bag + // PROTOTYPE: Report ERR_CollectionExpressionMissingAdd or similar if there are no errors in the bag // Probably shouldn't happen, but better safe than sorry. return; } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 36a5e56eb6ddc..2e38908bd80f0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 7964ca18eb710..cb1ad8210d590 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 8d07db6aa567e..00a8f212f9370 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index e005b35c31972..5a8985f99972b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 7f59d0885d7b9..2c787d89e314c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 9136c3ded5de2..fce51cc05ff0d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e697b5b6c02ca..c0d26108c0b2d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 46a02b0045eff..5e77b34f3decb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index bbd6e3dcf71ab..f23435934209d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index b630085e440cb..db6abdf3369e5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 1f229849cb79d..9f9680b146df1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index fbea061e7abef..69dae0da412ef 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index d8e596a36d9ae..2d423a4f77131 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -443,11 +443,6 @@ - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - Collection expression type must have an applicable instance or extension method 'Add' that can be called with an argument of iteration type '{0}'. The best overloaded method is '{1}'. - - - Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. Collection expression type '{0}' must have an instance or extension method 'Add' that can be called with a single argument. diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 8cafd8399817e..052484d301d4c 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -4509,18 +4509,18 @@ static void Main() // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = [default]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(7, 13), - // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(7, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[default]").WithArguments("string").WithLocation(7, 13), // (8,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [null]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[null]").WithArguments("string", "0").WithLocation(8, 13), // (8,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = [null]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(8, 13), - // (8,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (8,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(8, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[null]").WithArguments("string").WithLocation(8, 13), // (8,14): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type // s = [null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(8, 14), @@ -4530,18 +4530,18 @@ static void Main() // (9,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = ['a']; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(9, 13), - // (9,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (9,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(9, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "['a']").WithArguments("string").WithLocation(9, 13), // (10,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = [1]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(10, 13), // (10,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = [1]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(10, 13), - // (10,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (10,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(10, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("string").WithLocation(10, 13), // (10,14): error CS0029: Cannot implicitly convert type 'int' to 'char' // s = [1]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(10, 14), @@ -4551,9 +4551,9 @@ static void Main() // (11,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = [..""]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(11, 13), - // (11,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (11,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = [..""]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(11, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[..""""]").WithArguments("string").WithLocation(11, 13)); } [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] @@ -4585,9 +4585,9 @@ static void Main() // (6,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // _ = (string)[default]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("string", "Add").WithLocation(6, 21), - // (6,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (6,21): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("string").WithLocation(6, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[default]").WithArguments("string").WithLocation(6, 21), // (6,22): error CS8716: There is no target type for the default literal. // _ = (string)[default]; Diagnostic(ErrorCode.ERR_DefaultLiteralNoTargetType, "default").WithLocation(6, 22), @@ -4597,9 +4597,9 @@ static void Main() // (7,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // _ = (string)[null]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("string", "Add").WithLocation(7, 21), - // (7,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,21): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("string").WithLocation(7, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[null]").WithArguments("string").WithLocation(7, 21), // (7,22): error CS0037: Cannot convert null to 'char' because it is a non-nullable value type // _ = (string)[null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("char").WithLocation(7, 22), @@ -4609,18 +4609,18 @@ static void Main() // (8,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // _ = (string)['a']; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(8, 21), - // (8,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (8,21): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)['a']; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(8, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "['a']").WithArguments("string").WithLocation(8, 21), // (9,21): error CS1729: 'string' does not contain a constructor that takes 0 arguments // _ = (string)[1]; Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[1]").WithArguments("string", "0").WithLocation(9, 21), // (9,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // _ = (string)[1]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1]").WithArguments("string", "Add").WithLocation(9, 21), - // (9,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (9,21): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[1]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1]").WithArguments("string").WithLocation(9, 21), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1]").WithArguments("string").WithLocation(9, 21), // (9,22): error CS0029: Cannot implicitly convert type 'int' to 'char' // _ = (string)[1]; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "char").WithLocation(9, 22), @@ -4630,9 +4630,9 @@ static void Main() // (10,21): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // _ = (string)[..""]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(10, 21), - // (10,21): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (10,21): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // _ = (string)[..""]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[..""""]").WithArguments("string").WithLocation(10, 21)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[..""""]").WithArguments("string").WithLocation(10, 21)); } [Fact] @@ -5321,9 +5321,9 @@ struct S : IEnumerable // 1.cs(2,5): error CS1061: 'S' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'S' could be found (are you missing a using directive or an assembly reference?) // s = [1, 2]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2]").WithArguments("S", "Add").WithLocation(2, 5), - // 1.cs(2,5): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. + // 1.cs(2,5): error CS9215: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, 2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2]").WithArguments("S").WithLocation(2, 5), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2]").WithArguments("S").WithLocation(2, 5), // 1.cs(3,9): error CS9212: Spread operator '..' cannot operate on variables of type 'object' because 'object' does not contain a public instance or extension definition for 'GetEnumerator' // s = [.. new object()]; Diagnostic(ErrorCode.ERR_SpreadMissingMember, "new object()").WithArguments("object", "GetEnumerator").WithLocation(3, 9)); @@ -5845,9 +5845,9 @@ static void Main() // (13,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' // s = [1, ..s]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "S.Add(int, int)").WithLocation(13, 13), - // (13,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. + // (13,13): error CS9215: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(13, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("S").WithLocation(13, 13)); } [Fact] @@ -5877,9 +5877,9 @@ static void Main() // (15,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' // s = [1, ..s]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "S.Add(int, int)").WithLocation(15, 13), - // (15,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,13): error CS9215: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(15, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("S").WithLocation(15, 13)); } [Fact] @@ -5912,9 +5912,9 @@ static void Main() // (18,13): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'Extensions.Add(S, T, T)' // s = [1, ..s]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, ..s]").WithArguments("y", "Extensions.Add(S, T, T)").WithLocation(18, 13), - // (18,13): error CS9230: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. + // (18,13): error CS9215: Collection expression type 'S' must have an instance or extension method 'Add' that can be called with a single argument. // s = [1, ..s]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..s]").WithArguments("S").WithLocation(18, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("S").WithLocation(18, 13)); } [Fact] @@ -6234,9 +6234,9 @@ static void Main() // (7,13): error CS1061: 'string' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s = ['a']; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").WithLocation(7, 13), - // (7,13): error CS9230: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,13): error CS9215: Collection expression type 'string' must have an instance or extension method 'Add' that can be called with a single argument. // s = ['a']; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "['a']").WithArguments("string").WithLocation(7, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "['a']").WithArguments("string").WithLocation(7, 13)); } [Fact] @@ -6417,9 +6417,9 @@ static void Main() // (16,31): error CS0122: 'MyCollection.Add(int)' is inaccessible due to its protection level // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_BadAccess, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(16, 31), - // (16,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (16,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(16, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..x]").WithArguments("MyCollection").WithLocation(16, 31)); } [Fact] @@ -6458,9 +6458,9 @@ static void Main() // (6,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, ..x]").WithArguments("MyCollection", "Add").WithLocation(6, 31), - // (6,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (6,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(6, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..x]").WithArguments("MyCollection").WithLocation(6, 31)); } [Fact] @@ -6522,9 +6522,9 @@ static void Main() // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(out object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(out object)").WithLocation(15, 34), - // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -6557,9 +6557,9 @@ static void Main() // (15,34): error CS1954: The best overloaded method match 'MyCollection.Add(ref object)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("MyCollection.Add(ref object)").WithLocation(15, 34), - // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -6699,9 +6699,9 @@ static void Main() // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, out T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, out T)").WithLocation(18, 34), - // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (18,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); } [Fact] @@ -6737,9 +6737,9 @@ static void Main() // (18,34): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [..x, ..y, 3]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, ref T)").WithLocation(18, 34), - // (18,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (18,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [..x, ..y, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[..x, ..y, 3]").WithArguments("MyCollection").WithLocation(18, 34)); } [Fact] @@ -6888,18 +6888,18 @@ static void Main() // (18,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // x = ["2"]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, @"[""2""]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(18, 13), - // (18,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (18,13): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // x = ["2"]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[""2""]").WithArguments("MyCollection").WithLocation(18, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[""2""]").WithArguments("MyCollection").WithLocation(18, 13), // (20,21): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // y = new() { 3 }; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "3").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(20, 21), // (21,13): error CS1954: The best overloaded method match 'Extensions.Add(ref MyCollection, ref string)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // y = [4]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[4]").WithArguments("Extensions.Add(ref MyCollection, ref string)").WithLocation(21, 13), - // (21,13): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (21,13): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // y = [4]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[4]").WithArguments("MyCollection").WithLocation(21, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[4]").WithArguments("MyCollection").WithLocation(21, 13)); } [Fact] @@ -6928,9 +6928,9 @@ static void Main() // (14,31): error CS1921: The best overloaded method match for 'MyCollection.Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. // MyCollection y = [1, ..x]; Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "[1, ..x]").WithArguments("MyCollection.Add(int)").WithLocation(14, 31), - // (14,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (14,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, ..x]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, ..x]").WithArguments("MyCollection").WithLocation(14, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..x]").WithArguments("MyCollection").WithLocation(14, 31)); } [Fact] @@ -8065,9 +8065,9 @@ static void Main() // 0.cs(13,14): error CS0012: The type 'A2' is defined in an assembly that is not referenced. You must add a reference to assembly '6f8345f1-4f51-4a7a-a9f6-0597f76af3b9, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // y = [3, 4]; Diagnostic(ErrorCode.ERR_NoTypeDef, "[3, 4]").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 13), - // 0.cs(13,13): error CS9230: Collection expression type 'B2' must have an instance or extension method 'Add' that can be called with a single argument. + // 0.cs(13,13): error CS9215: Collection expression type 'B2' must have an instance or extension method 'Add' that can be called with a single argument. // y = [3, 4]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[3, 4]").WithArguments("B2").WithLocation(13, 13)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[3, 4]").WithArguments("B2").WithLocation(13, 13)); } [Fact] @@ -8169,15 +8169,15 @@ static void Main() // (7,13): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(int, int)' // d = [default]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[default]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(7, 13), - // (7,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,13): error CS9215: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(7, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[default]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(7, 13), // (8,13): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(int, int)' // d = [new KeyValuePair(1, 2)]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[new KeyValuePair(1, 2)]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(8, 13), - // (8,13): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. + // (8,13): error CS9215: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // d = [new KeyValuePair(1, 2)]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(8, 13), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(8, 13), // (9,15): error CS1003: Syntax error, ',' expected // d = [3:4]; Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",").WithLocation(9, 15), @@ -15123,9 +15123,9 @@ static void Main() // (19,44): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) // Container.MyCollection y = [null]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[null]").WithArguments("Container.MyCollection", "Add").WithLocation(19, 44), - // (19,44): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,44): error CS9215: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[null]").WithArguments("Container.MyCollection").WithLocation(19, 44), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[null]").WithArguments("Container.MyCollection").WithLocation(19, 44), // (19,45): error CS0037: Cannot convert null to 'int' because it is a non-nullable value type // Container.MyCollection y = [null]; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(19, 45)); @@ -15639,9 +15639,9 @@ static void Main() // (27,41): error CS1061: 'Container.MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'Container.MyCollection' could be found (are you missing a using directive or an assembly reference?) // Container.MyCollection y = [default]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("Container.MyCollection", "Add").WithLocation(27, 41), - // (27,41): error CS9230: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (27,41): error CS9215: Collection expression type 'Container.MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // Container.MyCollection y = [default]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[default]").WithArguments("Container.MyCollection").WithLocation(27, 41)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[default]").WithArguments("Container.MyCollection").WithLocation(27, 41)); } [CombinatorialData] @@ -16424,9 +16424,9 @@ static void Main() // (6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection y = [2]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[2]").WithArguments("MyCollection", "Add").WithLocation(6, 26), - // (6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (6,26): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [2]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[2]").WithArguments("MyCollection").WithLocation(6, 26)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[2]").WithArguments("MyCollection").WithLocation(6, 26)); } [CombinatorialData] @@ -16545,9 +16545,9 @@ static void Main() // 1.cs(6,26): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection y = [1, 2, 3]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, 3]").WithArguments("MyCollection", "Add").WithLocation(6, 26), - // 1.cs(6,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // 1.cs(6,26): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, 3]").WithArguments("MyCollection").WithLocation(6, 26)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2, 3]").WithArguments("MyCollection").WithLocation(6, 26)); } [Fact] @@ -16619,9 +16619,9 @@ static void Main() // 1.cs(6,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection y = [1, 2, null]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, null]").WithArguments("MyCollection", "Add").WithLocation(6, 34), - // 1.cs(6,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // 1.cs(6,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection y = [1, 2, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[1, 2, null]").WithArguments("MyCollection").WithLocation(6, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, 2, null]").WithArguments("MyCollection").WithLocation(6, 34)); } [Fact] @@ -25179,9 +25179,9 @@ .. GetConfig(), Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, @"[ .. GetConfig(), ]").WithArguments("value", "System.Collections.Generic.Dictionary.Add(string, object)").WithLocation(4, 52), - // (4,52): error CS9230: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. + // (4,52): error CS9215: Collection expression type 'Dictionary' must have an instance or extension method 'Add' that can be called with a single argument. // Dictionary Config => /**/[ - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, @"[ + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[ .. GetConfig(), ]").WithArguments("System.Collections.Generic.Dictionary").WithLocation(4, 52)); @@ -25728,9 +25728,9 @@ static MyCollection Create(int x, int[] y) // (5,26): error CS0118: 'Add' is a field but is used like a method // return /**/[x, ..y]/**/; Diagnostic(ErrorCode.ERR_BadSKknown, "[x, ..y]").WithArguments("Add", "field", "method").WithLocation(5, 26), - // (5,26): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (5,26): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // return /**/[x, ..y]/**/; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(5, 26)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(5, 26)); VerifyOperationTreeForTest(comp, """ @@ -35021,9 +35021,9 @@ static void Main() // (7,34): error CS0122: 'MyCollection.Add(int)' is inaccessible due to its protection level // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_BadAccess, "[x, ..y]").WithArguments("MyCollection.Add(int)").WithLocation(7, 34), - // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); string sourceB2 = """ partial class MyCollection @@ -35088,9 +35088,9 @@ static void Main() // (7,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 34), - // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); } [Fact] @@ -35137,9 +35137,9 @@ static void Main() // (7,34): error CS0122: 'MyCollectionBase.Add(object)' is inaccessible due to its protection level // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_BadAccess, "[x, ..y]").WithArguments("MyCollectionBase.Add(object)").WithLocation(7, 34), - // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); } [Fact] @@ -35271,9 +35271,9 @@ static void Main() // (15,32): error CS1954: The best overloaded method match 'MyCollection.Add(ref int?)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[x, ..y, null]").WithArguments("MyCollection.Add(" + refKind + " int?)").WithLocation(15, 32), - // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); } [Theory] @@ -35383,9 +35383,9 @@ static void Main() // (19,32): error CS1954: The best overloaded method match 'Extensions.Add(MyCollection, ref T)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[x, ..y, null]").WithArguments("Extensions.Add(MyCollection, " + refKind + " T)").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } [Theory] @@ -35641,9 +35641,9 @@ static void Main() // (15,32): error CS1501: No overload for method 'Add' takes 1 arguments // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_BadArgCount, "[x, ..y, null]").WithArguments("Add", "1").WithLocation(15, 32), - // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); } [Theory] @@ -35707,9 +35707,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int)' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("x", "MyCollection.Add(int?, int)").WithLocation(20, 40)); @@ -35781,9 +35781,9 @@ static void Main() // (15,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, ref readonly int, ref readonly int)' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "MyCollection.Add(int?, ref readonly int, ref readonly int)").WithLocation(15, 32), - // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); } else { @@ -35791,9 +35791,9 @@ static void Main() // (15,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'MyCollection.Add(int?, int, int)' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "MyCollection.Add(int?, " + refKind + "int, " + refKind + "int)").WithLocation(15, 32), - // (15,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 32)); } } @@ -35845,9 +35845,9 @@ static void Main() // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'index' of 'MyCollection.Add(int, ref int)' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("index", "MyCollection.Add(int, " + (useOut ? "out" : "ref") + " int)").WithLocation(7, 31), - // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'index' of 'MyCollection.Add(int, ref int)' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("index", $"MyCollection.Add(int, {(useOut ? "out" : "ref")} int)").WithLocation(8, 39)); @@ -36014,9 +36014,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?[])' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("y", "MyCollection.Add(int?, int?[])").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } [Fact] @@ -36051,9 +36051,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int?, int?, params int?[])' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int?, int?, params int?[])").WithLocation(20, 40)); @@ -36091,9 +36091,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'z' of 'MyCollection.Add(int?, int?, int?[])' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("z", "MyCollection.Add(int?, int?, int?[])").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS7036: There is no argument given that corresponds to the required parameter 'z' of 'MyCollection.Add(int?, int?, int?[])' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("z", "MyCollection.Add(int?, int?, int?[])").WithLocation(20, 40)); @@ -36262,9 +36262,9 @@ static void Main() // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int, params int)' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(int, params int)").WithLocation(7, 31), - // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31), // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(int, params int)' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "x").WithArguments("y", "MyCollection.Add(int, params int)").WithLocation(8, 39)); @@ -36390,9 +36390,9 @@ static void Main() // (7,31): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'MyCollection.Add(object, params object)' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y]").WithArguments("y", "MyCollection.Add(object, params object)").WithLocation(7, 31), - // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); } [Fact] @@ -36426,9 +36426,9 @@ static void Main() // (19,32): error CS1501: No overload for method 'Add' takes 1 arguments // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_BadArgCount, "[x, ..y, null]").WithArguments("Add", "1").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } [Theory] @@ -36503,9 +36503,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, ref readonly int, ref readonly int)' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, ref readonly int, ref readonly int)").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } else if (refKind == "in") { @@ -36513,9 +36513,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, in int, in int)' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, in int, in int)").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } else { @@ -36523,9 +36523,9 @@ static void Main() // (19,32): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'Extensions.Add(MyCollection, T, int, int)' // MyCollection z = [x, ..y, null]; Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[x, ..y, null]").WithArguments("x", "Extensions.Add(MyCollection, T, int, int)").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 32)); } } @@ -36793,9 +36793,9 @@ static void Main() // (20,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(20, 31), - // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (20,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); break; case "ref": comp.VerifyEmitDiagnostics( @@ -36805,9 +36805,9 @@ static void Main() // (20,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(20, 31), - // (20,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (20,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(20, 31)); break; } } @@ -36870,9 +36870,9 @@ static void Main() // (7,31): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 31), - // (7,31): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,31): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 31)); } [Fact] @@ -36907,9 +36907,9 @@ static void Main() // (19,32): error CS1929: 'MyCollection' does not contain a definition for 'Add' and the best extension method overload 'Extensions.Add(string, int)' requires a receiver of type 'string' // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_BadInstanceArgType, "[x, ..y]").WithArguments("MyCollection", "Add", "Extensions.Add(string, int)", "string").WithLocation(19, 32), - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,32): error CS1929: 'MyCollection' does not contain a definition for 'Add' and the best extension method overload 'Extensions.Add(string, int)' requires a receiver of type 'string' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_BadInstanceArgType, "new() { x }").WithArguments("MyCollection", "Add", "Extensions.Add(string, int)", "string").WithLocation(20, 32), @@ -36948,9 +36948,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (19,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(19, 32), // (20,40): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "x").WithArguments("MyCollection", "Add").WithLocation(20, 40) @@ -36995,9 +36995,9 @@ static void Main() } """; CreateCompilation([sourceA, sourceB1, s_collectionExtensions]).VerifyDiagnostics( - // (7,32): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,32): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 32), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 32), // (9,40): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Extensions.Add(MyCollection, params T[])' // MyCollection w = new() { x }; Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "x").WithArguments("Extensions.Add(MyCollection, params T[])", "T", "int?").WithLocation(9, 40) @@ -37113,9 +37113,9 @@ public static void Add(this {{(structOrClass == "struct" ? "ref" : "")}} T // (7,34): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[x, ..y]").WithArguments("MyCollection", "Add").WithLocation(7, 34), - // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); } @@ -37159,9 +37159,9 @@ static class Extensions // (7,34): error CS1921: The best overloaded method match for 'MyCollection.Add(object)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. // MyCollection z = [x, ..y]; Diagnostic(ErrorCode.ERR_InitializerAddHasWrongSignature, "[x, ..y]").WithArguments("MyCollection.Add(object)").WithLocation(7, 34), - // (7,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 34)); CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); } @@ -37234,9 +37234,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -37263,9 +37263,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (15,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(15, 34)); } [Fact] @@ -37344,9 +37344,9 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (19,34): error CS9230: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // (19,34): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollection z = [x, ..y, null]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 34)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y, null]").WithArguments("MyCollection").WithLocation(19, 34)); } [Fact] @@ -37854,9 +37854,9 @@ static void Main() // (7,35): error CS0012: The type 'MyCollectionA<>' is defined in an assembly that is not referenced. You must add a reference to assembly '41f5b758-1e64-4c10-88d8-6dd8029c374c, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. // MyCollectionB z = [x, ..y]; Diagnostic(ErrorCode.ERR_NoTypeDef, "[x, ..y]").WithArguments("MyCollectionA<>", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(7, 35), - // (7,35): error CS9230: Collection expression type 'MyCollectionB' must have an instance or extension method 'Add' that can be called with a single argument. + // (7,35): error CS9215: Collection expression type 'MyCollectionB' must have an instance or extension method 'Add' that can be called with a single argument. // MyCollectionB z = [x, ..y]; - Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd_New, "[x, ..y]").WithArguments("MyCollectionB").WithLocation(7, 35)); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollectionB").WithLocation(7, 35)); } [Fact] From d7811fce5385f03c78573c458165d1c20bc2a842 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:54:02 -0700 Subject: [PATCH 13/18] Update repro tests --- .../Semantics/CollectionExpressionTests.cs | 116 ++++++++++-------- 1 file changed, 65 insertions(+), 51 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 052484d301d4c..d318cd283aab2 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -34899,95 +34899,109 @@ static void Main() """); } + [WorkItem("https://github.com/dotnet/roslyn/issues/72098")] [Fact] - public void AddMethod_System_Windows_Input_InputGestureCollection() + public void AddMethod_Derived_01() { - string sourceA = """ + string source = """ using System.Collections; using System.Collections.Generic; - namespace System.Windows.Input + + class Element { } + + class ElementCollection : IEnumerable { - public class InputGesture - { - } - public sealed class InputGestureCollection : IList + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + public void Add(Element element) { _list.Add(element); } + } + + class Program + { + static void Main() { - private readonly List _list = new(); - object IList.this[int index] { get => _list[index]; set => _list[index] = value; } - bool IList.IsFixedSize => false; - bool IList.IsReadOnly => false; - int ICollection.Count => _list.Count; - bool ICollection.IsSynchronized => false; - object ICollection.SyncRoot => this; - int IList.Add(object value) => ((IList)_list).Add(value); - void IList.Clear() { _list.Clear(); } - bool IList.Contains(object value) => _list.Contains(value); - void ICollection.CopyTo(Array array, int index) => ((IList)_list).CopyTo(array, index); - IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); - int IList.IndexOf(object value) => _list.IndexOf(value); - void IList.Insert(int index, object value) => _list.Insert(index, value); - void IList.Remove(object value) => _list.Remove(value); - void IList.RemoveAt(int index) => _list.RemoveAt(index); - public int Add(InputGesture value) => ((IList)_list).Add(value); + ElementCollection c = [new Element(), null]; + c.Report(); } } """; - var comp = CreateCompilation(sourceA); - var refA = comp.EmitToImageReference(); + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[Element, null], "); + } + + [WorkItem("https://github.com/dotnet/roslyn/issues/72098")] + [Fact] + public void AddMethod_Derived_02() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + + class Base { } + class Element : Base { } + + class ElementCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public void Add(Element element) { _list.Add(element); } + } - string sourceB = """ - using System.Windows.Input; class Program { static void Main() { - InputGestureCollection c = [new InputGesture(), null]; + ElementCollection c = [new Element(), null]; c.Report(); } } """; - CompileAndVerify([sourceB, s_collectionExtensions], references: [refA], expectedOutput: "[System.Windows.Input.InputGesture, null], "); + CompileAndVerify([source, s_collectionExtensions], expectedOutput: "[Element, null], "); } + [WorkItem("https://github.com/dotnet/roslyn/issues/71240")] [Fact] - public void AddMethod_System_CommandLine_Command() + public void AddMethod_Derived_03() { string sourceA = """ using System.Collections; using System.Collections.Generic; - namespace System.CommandLine + + class Sample : IEnumerable { - public class Symbol - { - } - public class Argument : Symbol - { - } - public class Command : Symbol, IEnumerable + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T t) { if (t is object[] o) _list.Add(o); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() { - private readonly List _symbols = new(); - public IEnumerator GetEnumerator() => _symbols.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public void Add(Argument argument) { _symbols.Add(argument); } - public void Add(Command command) { _symbols.Add(command); } + Sample s = [["a"], ["b"], ["c"]]; + s.Report(); } } """; - var comp = CreateCompilation(sourceA); - var refA = comp.EmitToImageReference(); + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[[a], [b], [c]], "); - string sourceB = """ - using System.CommandLine; + string sourceB2 = """ class Program { static void Main() { - Command c = [new Argument(), new Command()]; - c.Report(); + Sample s = ["a", null]; } } """; - CompileAndVerify([sourceB, s_collectionExtensions], references: [refA], expectedOutput: "[System.CommandLine.Argument, []], "); + var comp = CreateCompilation([sourceA, sourceB2]); + comp.VerifyEmitDiagnostics( + // (5,29): error CS0029: Cannot implicitly convert type 'string' to 'object[]' + // Sample s = ["a", null]; + Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""a""").WithArguments("string", "object[]").WithLocation(5, 29)); } [Fact] From 59bfc0d64e23e7a472655d49e3a432e2c06bb39a Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:59:53 -0700 Subject: [PATCH 14/18] Update breaking change description --- .../Compiler Breaking Changes - DotNet 8.md | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md index 21a6b0e2e4cb1..76b8741267d6e 100644 --- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md +++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md @@ -35,7 +35,7 @@ public class C *Conversion* of a collection expression to a `struct` or `class` that implements `System.Collections.IEnumerable` and *does not* have a `CollectionBuilderAttribute` requires the target type to have an accessible constructor that can be called with no arguments and, if the collection expression is not empty, the target type must have an accessible `Add` method -that can be called with a single argument of [*iteration type*](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/statements.md#1395-the-foreach-statement) of the target type. +that can be called with a single argument. Previously, the constructor and `Add` methods were required for *construction* of the collection instance but not for *conversion*. That meant the following call was ambiguous since both `char[]` and `string` were valid target types for the collection expression. @@ -47,24 +47,6 @@ static void Print(char[] arg) { } static void Print(string arg) { } ``` -Previously, the collection expression in `y = [1, 2, 3]` was allowed since construction only requires an applicable `Add` method for each element expression. -The collection expression is now an error because of the conversion requirement for an `Add` method than be called with an argument of the iteration type `object`. -```csharp -// ok: Add is not required for empty collection -MyCollection x = []; - -// error CS9215: Collection expression type must have an applicable instance or extension method 'Add' -// that can be called with an argument of iteration type 'object'. -// The best overloaded method is 'MyCollection.Add(int)'. -MyCollection y = [1, 2, 3]; - -class MyCollection : IEnumerable -{ - public void Add(int i) { ... } - IEnumerator IEnumerable.GetEnumerator() { ... } -} -``` - ## `ref` arguments can be passed to `in` parameters ***Introduced in Visual Studio 2022 version 17.8p2*** From 70f94fb7a8005f7030ae211327d2d905244669d9 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:50:54 -0700 Subject: [PATCH 15/18] Test additional code path --- .../Portable/Binder/Binder_Conversions.cs | 1 - .../Semantics/CollectionExpressionTests.cs | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 7b642b77c002d..449a3311d9614 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1236,7 +1236,6 @@ static ImmutableArray filterOutBadGenericMethods( var conversion = conversions.ConvertExtensionMethodThisArg(constructed.Parameters[0].Type, receiverType, ref useSiteInfo); if (!conversion.Exists) { - // PROTOTYPE: Test this code path continue; // Conversion to 'this' parameter failed } } diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index d318cd283aab2..945fcb2d14a25 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -36971,6 +36971,56 @@ static void Main() ); } + [Fact] + public void AddMethod_Extension_12_WrongThisType() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB1, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB2]); + comp.VerifyEmitDiagnostics( + // (7,39): error CS9215: Collection expression type 'MyCollection' must have an instance or extension method 'Add' that can be called with a single argument. + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[x, ..y]").WithArguments("MyCollection").WithLocation(7, 39)); + } + [Fact] public void AddMethod_Extension_12_ConstraintsViolated() { From 4330e53b711f82bf226a268e0e85b2e7a6ce7d5e Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:08:47 -0700 Subject: [PATCH 16/18] dynamic extension test --- .../Semantics/CollectionExpressionTests.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 945fcb2d14a25..8ff7f89d07049 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -37022,7 +37022,7 @@ static void Main() } [Fact] - public void AddMethod_Extension_12_ConstraintsViolated() + public void AddMethod_Extension_13_ConstraintsViolated() { string sourceA = """ using System.Collections; @@ -37068,6 +37068,41 @@ static void Main() ); } + [Fact] + public void AddMethod_Extension_14_Dynamic() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this dynamic d, T t) { d.__AddInternal(t); } + } + """; + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB]); + comp.VerifyEmitDiagnostics( + // (11,36): error CS1103: The first parameter of an extension method cannot be of type 'dynamic' + // public static void Add(this dynamic d, T t) { d.__AddInternal(t); } + Diagnostic(ErrorCode.ERR_BadTypeforThis, "dynamic").WithArguments("dynamic").WithLocation(11, 36)); + } + [Fact] public void AddMethod_Base() { @@ -38621,8 +38656,5 @@ static void Test(MyCollection a) Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[1]").WithArguments("Create", "long", "MyCollection").WithLocation(5, 14) ); } - - // PROTOTYPE: Can we extend 'dynamic' type? - // If so, test an 'Add' method like that. } } From 69d499d9c3eea2c0e47cc0eb480c5814ccac757f Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:57:12 -0700 Subject: [PATCH 17/18] Address some PROTOTYPE comments and PR feedback --- .../Portable/Binder/Binder_Conversions.cs | 2 +- .../Semantics/Conversions/Conversions.cs | 2 - .../Semantics/CollectionExpressionTests.cs | 146 +++++++++++++++++- 3 files changed, 144 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 449a3311d9614..ddf599a86d052 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -1197,7 +1197,7 @@ static ImmutableArray filterOutBadGenericMethods( argToParamMap: default, argumentRefKinds: analyzedArguments.RefKinds, isMethodGroupConversion: false, - allowRefOmittedArguments: methodGroup.ReceiverOpt.IsExpressionOfComImportType(), // PROTOTYPE: Test effect of this flag + allowRefOmittedArguments: methodGroup.ReceiverOpt.IsExpressionOfComImportType(), binder: addMethodBinder, expanded: candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm, parameterTypes: out ImmutableArray parameterTypes, diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 9cbb8ed1d6331..abb608ffe3b20 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -198,8 +198,6 @@ protected override Conversion GetCollectionExpressionConversion( { return Conversion.NoConversion; } - - // PROTOTYPE: Probably should at least accumulate dependencies and propagate them in case of success. } var builder = ArrayBuilder.GetInstance(elements.Length); diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 8ff7f89d07049..31e5bd398a5de 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -37022,7 +37022,40 @@ static void Main() } [Fact] - public void AddMethod_Extension_13_ConstraintsViolated() + public void AddMethod_Extension_13_WrongThisType() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions + { + public static void Add(this IEnumerable collection, T t) { ((MyCollection)collection).__AddInternal(t); } + } + """; + string sourceB = """ + class Program + { + static void Main() + { + string x = "1"; + string[] y = ["2", "3"]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + """; + CompileAndVerify([sourceA, sourceB, s_collectionExtensions], expectedOutput: "[1, 2, 3], "); + } + + [Fact] + public void AddMethod_Extension_14_ConstraintsViolated() { string sourceA = """ using System.Collections; @@ -37069,7 +37102,7 @@ static void Main() } [Fact] - public void AddMethod_Extension_14_Dynamic() + public void AddMethod_Extension_15_Dynamic() { string sourceA = """ using System.Collections; @@ -37103,6 +37136,45 @@ static void Main() Diagnostic(ErrorCode.ERR_BadTypeforThis, "dynamic").WithArguments("dynamic").WithLocation(11, 36)); } + [WorkItem("https://github.com/dotnet/roslyn/issues/72769")] + [Fact] + public void AddMethod_RefOmittedArguments() + { + string sourceA = """ + using System; + using System.Collections; + using System.Runtime.InteropServices; + + [ComImport] + [Guid("5CDF1E39-B461-4A9B-9359-1D6F7DECE1B3")] + class MyCollection : IEnumerable + { + extern IEnumerator IEnumerable.GetEnumerator(); + } + + static class Extensions + { + public static void Add(this MyCollection collection, ref T x) => throw null; + } + """; + string sourceB = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + MyCollection w = new() { x }; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB]); + // https://github.com/dotnet/roslyn/issues/72769: VerifyEmitDiagnostics() results in Debug.Assert + // failures in LocalRewriter.MakeCollectionInitializer() and GetEffectiveArgumentRefKinds(). + comp.VerifyDiagnostics(); + } + [Fact] public void AddMethod_Base() { @@ -37714,7 +37786,7 @@ static void Main() } [Fact] - public void AddMethod_Unsafe() + public void AddMethod_Unsafe_01() { string sourceA = """ using System.Collections; @@ -37765,6 +37837,74 @@ static class Extensions CompileAndVerify([sourceA, sourceB, sourceC, s_collectionExtensions], options: TestOptions.UnsafeReleaseExe, expectedOutput: "[1, 2, 3], "); } + [Fact] + public void AddMethod_Unsafe_02() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private readonly List _list = new(); + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + internal void __AddInternal(T t) { _list.Add(t); } + } + static class Extensions1 + { + unsafe public static void Add(this MyCollection collection, void* p) => throw null; + } + """; + + string sourceB1 = """ + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + } + } + """; + var comp = CreateCompilation([sourceA, sourceB1, s_collectionExtensions], options: TestOptions.UnsafeReleaseExe); + comp.VerifyEmitDiagnostics( + // (7,35): error CS1950: The best overloaded Add method 'Extensions1.Add(MyCollection, void*)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("Extensions1.Add(MyCollection, void*)").WithLocation(7, 35), + // (7,35): error CS1503: Argument 2: cannot convert from 'int' to 'void*' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("2", "int", "void*").WithLocation(7, 35), + // (7,38): error CS1503: Argument 2: cannot convert from 'int' to 'void*' + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgType, "..y").WithArguments("2", "int", "void*").WithLocation(7, 38), + // (7,40): error CS1950: The best overloaded Add method 'Extensions1.Add(MyCollection, void*)' for the collection initializer has some invalid arguments + // MyCollection z = [x, ..y]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("Extensions1.Add(MyCollection, void*)").WithLocation(7, 40)); + + string sourceB2 = """ + using N; + class Program + { + static void Main() + { + int x = 1; + int[] y = [2, 3]; + MyCollection z = [x, ..y]; + z.Report(); + } + } + namespace N + { + static class Extensions2 + { + public static void Add(this MyCollection collection, T t) { collection.__AddInternal(t); } + } + } + """; + CompileAndVerify([sourceA, sourceB2, s_collectionExtensions], options: TestOptions.UnsafeReleaseExe, expectedOutput: "[1, 2, 3], "); + } + [Fact] public void AddMethod_RefStruct_01() { From 1316830726b2ba7cbaa4b263bf3089f24444a79d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Thu, 28 Mar 2024 03:21:48 -0700 Subject: [PATCH 18/18] Skip failing test --- .../CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 31e5bd398a5de..185b83c55252d 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -37137,7 +37137,7 @@ static void Main() } [WorkItem("https://github.com/dotnet/roslyn/issues/72769")] - [Fact] + [Fact(Skip = "https://github.com/dotnet/roslyn/issues/72769")] public void AddMethod_RefOmittedArguments() { string sourceA = """ @@ -37172,7 +37172,7 @@ static void Main() var comp = CreateCompilation([sourceA, sourceB]); // https://github.com/dotnet/roslyn/issues/72769: VerifyEmitDiagnostics() results in Debug.Assert // failures in LocalRewriter.MakeCollectionInitializer() and GetEffectiveArgumentRefKinds(). - comp.VerifyDiagnostics(); + comp.VerifyEmitDiagnostics(); } [Fact]