diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md index 25058781d37d6..2d960d3a31cc8 100644 --- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md +++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md @@ -1,5 +1,42 @@ # This document lists known breaking changes in Roslyn after .NET 7 all the way to .NET 8. +## Collection expression target type must have constructor and `Add` method + +***Introduced in Visual Studio 2022 version 17.10*** + +*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. + +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. +The call is no longer ambiguous because `string` does not have a parameterless constructor or `Add` method. +```csharp +Print(['a', 'b', 'c']); // calls Print(char[]) + +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*** diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs index 889b78bfd34c0..37e3bdc1f4dac 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs @@ -5151,6 +5151,138 @@ void M() """); } + [Fact] + public async Task TestInDictionary_Empty() + { + await TestInRegularAndScriptAsync( + """ + using System.Collections.Generic; + class Program + { + static void Main() + { + Dictionary d = [|new|] Dictionary() { }; + } + } + """, + """ + using System.Collections.Generic; + class Program + { + static void Main() + { + Dictionary d = []; + } + } + """); + } + + [Fact] + public async Task TestInDictionary_NotEmpty() + { + await TestMissingInRegularAndScriptAsync( + """ + using System.Collections.Generic; + class Program + { + static void Main() + { + Dictionary d = new Dictionary() { { string.Empty, null } }; + } + } + """); + } + + [Fact] + public async Task TestInIEnumerableAndIncompatibleAdd_Empty() + { + await TestInRegularAndScriptAsync( + """ + using System.Collections; + class Program + { + static void Main() + { + MyCollection c = [|new|] MyCollection() { }; + } + } + class MyCollection : IEnumerable + { + public void Add(string s) { } + IEnumerator IEnumerable.GetEnumerator() => null; + } + """, + """ + using System.Collections; + class Program + { + static void Main() + { + MyCollection c = []; + } + } + class MyCollection : IEnumerable + { + public void Add(string s) { } + IEnumerator IEnumerable.GetEnumerator() => null; + } + """); + } + + [Fact] + public async Task TestInIEnumerableAndIncompatibleAdd_NotEmpty() + { + await new VerifyCS.Test + { + ReferenceAssemblies = Testing.ReferenceAssemblies.NetCore.NetCoreApp31, + TestCode = """ + using System.Collections; + class Program + { + static void Main() + { + MyCollection c = [|new|] MyCollection() { "a", "b" }; + } + } + class MyCollection : IEnumerable + { + public void Add(string s) { } + IEnumerator IEnumerable.GetEnumerator() => null; + } + """, + FixedCode = """ + using System.Collections; + class Program + { + static void Main() + { + MyCollection c = ["a", "b"]; + } + } + class MyCollection : IEnumerable + { + public void Add(string s) { } + IEnumerator IEnumerable.GetEnumerator() => null; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + TestState = + { + 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(); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71607")] public async Task TestAddRangeOfCollectionExpression1() { diff --git a/src/Compilers/CSharp/Portable/Binder/BinderFlags.cs b/src/Compilers/CSharp/Portable/Binder/BinderFlags.cs index 52ff59ae2547a..5a67fe48ff74a 100644 --- a/src/Compilers/CSharp/Portable/Binder/BinderFlags.cs +++ b/src/Compilers/CSharp/Portable/Binder/BinderFlags.cs @@ -112,6 +112,12 @@ internal enum BinderFlags : uint /// InExpressionTree = 1 << 30, + /// + /// Indicates the binder is used during collection expression conversion + /// to verify applicable methods are available. + /// + CollectionExpressionConversionValidation = 1u << 31, + // Groups AllClearedAtExecutableCodeBoundary = InLockBody | InCatchBlock | InCatchFilter | InFinallyBlock | InTryBlockOfTryCatch | InNestedFinallyBlock, diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index c5290f1ed83eb..e7d95a83aae0e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -654,35 +654,25 @@ private BoundCollectionExpression ConvertCollectionExpression( if (collectionTypeKind is CollectionExpressionTypeKind.ImplementsIEnumerable) { implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; - if (targetType is NamedTypeSymbol namedType) - { - var analyzedArguments = AnalyzedArguments.GetInstance(); - // https://github.com/dotnet/roslyn/issues/68785: Use ctor with `int capacity` when the size is known. - collectionCreation = BindClassCreationExpression(syntax, namedType.Name, syntax, namedType, analyzedArguments, diagnostics); - collectionCreation.WasCompilerGenerated = true; - analyzedArguments.Free(); - } - else if (targetType is TypeParameterSymbol typeParameter) - { - var analyzedArguments = AnalyzedArguments.GetInstance(); - collectionCreation = BindTypeParameterCreationExpression(syntax, typeParameter, analyzedArguments, initializerOpt: null, typeSyntax: syntax, wasTargetTyped: true, diagnostics); - collectionCreation.WasCompilerGenerated = true; - analyzedArguments.Free(); - } - else - { - collectionCreation = new BoundBadExpression(syntax, LookupResultKind.NotCreatable, ImmutableArray.Empty, ImmutableArray.Empty, targetType); - } + collectionCreation = BindCollectionExpressionConstructor(syntax, targetType, diagnostics); var collectionInitializerAddMethodBinder = this.WithAdditionalFlags(BinderFlags.CollectionInitializerAddMethod); foreach (var element in elements) { - BoundNode convertedElement = BindCollectionExpressionElementAddMethod( - element, - collectionInitializerAddMethodBinder, - implicitReceiver, - diagnostics, - out _); + BoundNode convertedElement = element is BoundCollectionExpressionSpreadElement spreadElement ? + (BoundNode)BindCollectionExpressionSpreadElementAddMethod( + (SpreadElementSyntax)spreadElement.Syntax, + spreadElement, + collectionInitializerAddMethodBinder, + implicitReceiver, + diagnostics) : + BindCollectionInitializerElementAddMethod( + (ExpressionSyntax)element.Syntax, + ImmutableArray.Create((BoundExpression)element), + hasEnumerableInitializerType: true, + collectionInitializerAddMethodBinder, + diagnostics, + implicitReceiver); builder.Add(convertedElement); } } @@ -766,6 +756,50 @@ BoundNode bindSpreadElement(BoundCollectionExpressionSpreadElement element, Type } } + internal BoundExpression BindCollectionExpressionConstructor(SyntaxNode syntax, TypeSymbol targetType, BindingDiagnosticBag diagnostics) + { + BoundExpression collectionCreation; + var analyzedArguments = AnalyzedArguments.GetInstance(); + if (targetType is NamedTypeSymbol namedType) + { + var binder = WithAdditionalFlags(BinderFlags.CollectionExpressionConversionValidation); + collectionCreation = binder.BindClassCreationExpression(syntax, namedType.Name, syntax, namedType, analyzedArguments, diagnostics); + collectionCreation.WasCompilerGenerated = true; + } + else if (targetType is TypeParameterSymbol typeParameter) + { + collectionCreation = BindTypeParameterCreationExpression(syntax, typeParameter, analyzedArguments, initializerOpt: null, typeSyntax: syntax, wasTargetTyped: true, diagnostics); + collectionCreation.WasCompilerGenerated = true; + } + else + { + throw ExceptionUtilities.UnexpectedValue(targetType); + } + analyzedArguments.Free(); + return collectionCreation; + } + + internal bool HasCollectionExpressionApplicableConstructor(SyntaxNode syntax, TypeSymbol targetType, BindingDiagnosticBag diagnostics) + { + var collectionCreation = BindCollectionExpressionConstructor(syntax, targetType, diagnostics); + return !collectionCreation.HasErrors; + } + + internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, TypeSymbol targetType, TypeSymbol elementType, BindingDiagnosticBag diagnostics) + { + var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; + var elementPlaceholder = new BoundValuePlaceholder(syntax, elementType) { WasCompilerGenerated = true }; + var addMethodBinder = WithAdditionalFlags(BinderFlags.CollectionInitializerAddMethod | BinderFlags.CollectionExpressionConversionValidation); + var result = BindCollectionInitializerElementAddMethod( + syntax, + ImmutableArray.Create(elementPlaceholder), + hasEnumerableInitializerType: true, + addMethodBinder, + diagnostics, + implicitReceiver); + return !result.HasErrors; + } + /// /// 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 @@ -865,10 +899,24 @@ private void GenerateImplicitConversionErrorForCollectionExpression( if (collectionTypeKind != CollectionExpressionTypeKind.None) { + var elements = node.Elements; var elementType = elementTypeWithAnnotations.Type; Debug.Assert(elementType is { }); - var elements = node.Elements; + if (collectionTypeKind == CollectionExpressionTypeKind.ImplementsIEnumerable) + { + if (!HasCollectionExpressionApplicableConstructor(node.Syntax, targetType, diagnostics)) + { + reportedErrors = true; + } + + if (elements.Length > 0 && + !HasCollectionExpressionApplicableAddMethod(node.Syntax, targetType, elementType, diagnostics)) + { + reportedErrors = true; + } + } + var useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); foreach (var element in elements) { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 5283dc51d063b..c627a235e3a7d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -5819,7 +5819,7 @@ private BoundExpression BindUnexpectedComplexElementInitializer(InitializerExpre } private BoundExpression BindCollectionInitializerElementAddMethod( - ExpressionSyntax elementInitializer, + SyntaxNode elementInitializer, ImmutableArray boundElementInitializerExpressions, bool hasEnumerableInitializerType, Binder collectionInitializerAddMethodBinder, @@ -5937,31 +5937,6 @@ static void copyRelevantAddMethodDiagnostics(BindingDiagnosticBag source, Bindin } #nullable enable - internal BoundNode BindCollectionExpressionElementAddMethod( - BoundNode element, - Binder collectionInitializerAddMethodBinder, - BoundObjectOrCollectionValuePlaceholder implicitReceiver, - BindingDiagnosticBag diagnostics, - out bool hasErrors) - { - var result = element is BoundCollectionExpressionSpreadElement spreadElement ? - (BoundNode)BindCollectionExpressionSpreadElementAddMethod( - (SpreadElementSyntax)spreadElement.Syntax, - spreadElement, - collectionInitializerAddMethodBinder, - implicitReceiver, - diagnostics) : - BindCollectionInitializerElementAddMethod( - (ExpressionSyntax)element.Syntax, - ImmutableArray.Create((BoundExpression)element), - hasEnumerableInitializerType: true, - collectionInitializerAddMethodBinder, - diagnostics, - implicitReceiver); - hasErrors = result.HasErrors; - return result; - } - private BoundCollectionExpressionSpreadElement BindCollectionExpressionSpreadElementAddMethod( SpreadElementSyntax syntax, BoundCollectionExpressionSpreadElement element, diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 2e0286cc994a5..af3cd2594dcc1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -9,7 +9,6 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { @@ -182,8 +181,22 @@ protected override Conversion GetCollectionExpressionConversion( } Debug.Assert(elementType is { }); - var elements = node.Elements; + + if (collectionTypeKind == CollectionExpressionTypeKind.ImplementsIEnumerable) + { + if (!_binder.HasCollectionExpressionApplicableConstructor(syntax, targetType, BindingDiagnosticBag.Discarded)) + { + return Conversion.NoConversion; + } + + if (elements.Length > 0 && + !_binder.HasCollectionExpressionApplicableAddMethod(syntax, targetType, elementType, BindingDiagnosticBag.Discarded)) + { + return Conversion.NoConversion; + } + } + var builder = ArrayBuilder.GetInstance(elements.Length); foreach (var element in elements) { diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index c498cf2576007..4d2ea1b3e8e8c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -2570,10 +2570,10 @@ kind2 is CollectionExpressionTypeKind.Span && return true; } - // - T1 is System.ReadOnlySpan or System.Span, and T2 is an array_or_array_interface_or_string_type + // - T1 is System.ReadOnlySpan or System.Span, and T2 is an array_or_array_interface // with iteration type E2, and an implicit conversion exists from E1 to E2 if (kind1 is CollectionExpressionTypeKind.ReadOnlySpan or CollectionExpressionTypeKind.Span && - IsSZArrayOrArrayInterfaceOrString(t2, out elementType2) && + IsSZArrayOrArrayInterface(t2, out elementType2) && hasImplicitConversion(elementType1, elementType2, ref useSiteInfo)) { return true; @@ -2593,14 +2593,8 @@ bool hasImplicitConversion(TypeSymbol source, TypeSymbol destination, ref Compou Conversions.ClassifyImplicitConversionFromType(source, destination, ref useSiteInfo).IsImplicit; } - private bool IsSZArrayOrArrayInterfaceOrString(TypeSymbol type, out TypeSymbol elementType) + private static bool IsSZArrayOrArrayInterface(TypeSymbol type, out TypeSymbol elementType) { - if (type.SpecialType == SpecialType.System_String) - { - elementType = Compilation.GetSpecialType(SpecialType.System_Char); - return true; - } - if (type is ArrayTypeSymbol { IsSZArray: true } arrayType) { elementType = arrayType.ElementType; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs index 06224cc01be63..68b771061ee68 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs @@ -504,8 +504,25 @@ internal void ReportDiagnostics( // but no argument was supplied for it then the first such method is // the best bad method. case MemberResolutionKind.RequiredParameterMissing: - // CONSIDER: for consistency with dev12, we would goto default except in omitted ref cases. - ReportMissingRequiredParameter(firstSupported, diagnostics, delegateTypeBeingInvoked, symbols, location); + if ((binder.Flags & BinderFlags.CollectionExpressionConversionValidation) != 0) + { + if (receiver is null) + { + Debug.Assert(firstSupported.Member is MethodSymbol { MethodKind: MethodKind.Constructor }); + diagnostics.Add(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); + } + } + else + { + // CONSIDER: for consistency with dev12, we would goto default except in omitted ref cases. + ReportMissingRequiredParameter(firstSupported, diagnostics, delegateTypeBeingInvoked, symbols, location); + } return; // NOTE: For some reason, there is no specific handling for this result kind. @@ -1092,9 +1109,12 @@ private bool HadBadArguments( // ErrorCode.ERR_BadArgTypesForCollectionAdd or ErrorCode.ERR_InitializerAddHasParamModifiers // as there is no explicit call to Add method. - foreach (var parameter in method.GetParameters()) + int argumentOffset = arguments.IsExtensionMethodInvocation ? 1 : 0; + var parameters = method.GetParameters(); + + for (int i = argumentOffset; i < parameters.Length; i++) { - if (parameter.RefKind != RefKind.None) + if (parameters[i].RefKind != RefKind.None) { // The best overloaded method match '{0}' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters. diagnostics.Add(ErrorCode.ERR_InitializerAddHasParamModifiers, location, symbols, method); @@ -1102,8 +1122,16 @@ private bool HadBadArguments( } } - // The best overloaded Add method '{0}' for the collection initializer has some invalid arguments - diagnostics.Add(ErrorCode.ERR_BadArgTypesForCollectionAdd, location, symbols, method); + if (flags.Includes(BinderFlags.CollectionExpressionConversionValidation)) + { + Debug.Assert(arguments.Arguments.Count == argumentOffset + 1); + diagnostics.Add(ErrorCode.ERR_CollectionExpressionMissingAdd, location, arguments.Arguments[argumentOffset].Type, method); + } + else + { + // The best overloaded Add method '{0}' for the collection initializer has some invalid arguments + diagnostics.Add(ErrorCode.ERR_BadArgTypesForCollectionAdd, location, symbols, method); + } } foreach (var arg in badArg.Result.BadArgumentsOpt.TrueBits()) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 93093f92a9b20..171ac911a1444 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6859,6 +6859,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Collection expression target '{0}' has no element type. + + 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}'. + 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 e3e945e05b48e..35c2173076765 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2282,6 +2282,8 @@ internal enum ErrorCode ERR_InvalidExperimentalDiagID = 9211, ERR_SpreadMissingMember = 9212, ERR_CollectionExpressionTargetNoElementType = 9213, + ERR_CollectionExpressionMissingConstructor = 9214, + ERR_CollectionExpressionMissingAdd = 9215, #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index a40daa23293fa..b0a40cadb3c33 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2411,6 +2411,8 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code) case ErrorCode.ERR_InvalidExperimentalDiagID: case ErrorCode.ERR_SpreadMissingMember: case ErrorCode.ERR_CollectionExpressionTargetNoElementType: + case ErrorCode.ERR_CollectionExpressionMissingConstructor: + case ErrorCode.ERR_CollectionExpressionMissingAdd: 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 3355fc997c12b..ca905f63dcc40 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -432,6 +432,16 @@ Tuto verzi {0} nelze použít s výrazy kolekce. + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 11b28df4971c2..9901d1ad9015f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -432,6 +432,16 @@ Diese Version von „{0}“ kann nicht mit Auflistungsausdrücken verwendet werden. + + 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 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. + + There is no target type for the collection expression. Für den Sammlungsausdruck ist kein Zieltyp vorhanden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 15d350f41e9c2..b44db9bc4b716 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -432,6 +432,16 @@ Esta versión de '{0}' no se puede usar con expresiones de colección. + + 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 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. + + There is no target type for the collection expression. No hay ningún tipo de destino para la expresión de colección. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 44292689a127c..6d6d70058082c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -432,6 +432,16 @@ Cette version de « {0} » ne peut pas être utilisée avec des expressions de collection. + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 4a9e08eb8b387..1d66800f68b1f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -432,6 +432,16 @@ Questa versione di '{0}' non può essere utilizzata con espressioni di raccolta. + + 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 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. + + There is no target type for the collection expression. Nessun tipo di destinazione per l'espressione di raccolta. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 822c0095ea75a..a07e0bd4ce044 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -432,6 +432,16 @@ このバージョンの '{0}' は、コレクション式では使用できません。 + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index cdab931274135..68546d1409fda 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -432,6 +432,16 @@ 이 버전의 '{0}'은(는) 컬렉션 식과 함께 사용할 수 없습니다. + + 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 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. + + There is no target type for the collection expression. 컬렉션 식에 대한 대상 형식이 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 386d274db47af..4ea9a155eb112 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -432,6 +432,16 @@ Tej wersji elementu „{0}” nie można używać z wyrażeniami kolekcji. + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 6b0fc279fd701..fa097509f1fb7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -432,6 +432,16 @@ Esta versão de '{0}' não pode ser usada com expressões de coleção. + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index dc5cd33c31452..ac193c0fff6f0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -432,6 +432,16 @@ Невозможно использовать эту версию "{0}" с выражениями коллекций. + + 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 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. + + There is no target type for the collection expression. Отсутствует тип целевого объекта для выражения коллекции. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 07074f767e8b7..702f0d962d18a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -432,6 +432,16 @@ Bu '{0}' sürümü koleksiyon ifadeleri ile kullanılamaz. + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 5206649fec756..5fff182a64966 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -432,6 +432,16 @@ “{0}”的此版本无法与集合表达式一起使用。 + + 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 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. + + There is no target type for the collection expression. 集合表达式没有目标类型。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index cd2428ed9b358..d5ba7c8641c79 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -432,6 +432,16 @@ 此版本的 '{0}' 無法與集合運算式一起使用。 + + 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 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. + + There is no target type for the collection expression. There is no target type for the collection expression. diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 1698fd57e7522..c0de6ab33bb4a 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -875,8 +875,9 @@ public void OverloadResolution_07() string source = """ using System.Collections; using System.Collections.Generic; - struct S : IEnumerable + struct S : IEnumerable { + IEnumerator IEnumerable.GetEnumerator() => null; IEnumerator IEnumerable.GetEnumerator() => null; public void Add(int i) { } } @@ -895,12 +896,12 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (16,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F1(S)' and 'Program.F1(List)' + // (17,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F1(S)' and 'Program.F1(List)' // var x = F1([1]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F1").WithArguments("Program.F1(S)", "Program.F1(System.Collections.Generic.List)").WithLocation(16, 17), - // (17,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F2(List)' and 'Program.F2(S)' + Diagnostic(ErrorCode.ERR_AmbigCall, "F1").WithArguments("Program.F1(S)", "Program.F1(System.Collections.Generic.List)").WithLocation(17, 17), + // (18,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F2(List)' and 'Program.F2(S)' // var y = F2([2]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F2").WithArguments("Program.F2(System.Collections.Generic.List)", "Program.F2(S)").WithLocation(17, 17)); + Diagnostic(ErrorCode.ERR_AmbigCall, "F2").WithArguments("Program.F2(System.Collections.Generic.List)", "Program.F2(S)").WithLocation(18, 17)); } [Fact] @@ -1009,9 +1010,9 @@ public void OverloadResolution_ElementConversions_03() using System.Collections.Generic; class MyCollection : IEnumerable { - private List _items = new(); + private List _items = new(); IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator(); - public void Add(int i) { _items.Add(i); } + public void Add(object o) { _items.Add(o); } } class Program { @@ -1041,9 +1042,10 @@ public void OverloadResolution_ElementConversions_04() string source = """ using System.Collections; using System.Collections.Generic; - class MyCollection : IEnumerable + class MyCollection : IEnumerable { private List _items = new(); + IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator(); public void Add(int? i) { _items.Add(i); } } @@ -1074,14 +1076,16 @@ public void OverloadResolution_ElementConversions_05() using System.Collections.Generic; class MyCollection1 : IEnumerable { - private List _items = new(); + private List _items = new(); IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator(); + public void Add(object o) { _items.Add(o); } public void Add(int? i) { _items.Add(i); } } class MyCollection2 : IEnumerable { private List _items = new(); IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator(); + public void Add(object o) { _items.Add(o); } public void Add(int i) { _items.Add(i); } public void Add(string s) { _items.Add(s); } } @@ -1098,12 +1102,12 @@ static void Main() } """; CreateCompilation(source).VerifyEmitDiagnostics( - // (22,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(MyCollection1)' and 'Program.F(MyCollection2)' - // var x = F([1, (string)null]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(MyCollection1)", "Program.F(MyCollection2)").WithLocation(22, 17), // (24,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(MyCollection1)' and 'Program.F(MyCollection2)' + // var x = F([1, (string)null]); + Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(MyCollection1)", "Program.F(MyCollection2)").WithLocation(24, 17), + // (26,17): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(MyCollection1)' and 'Program.F(MyCollection2)' // var z = F([..y]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(MyCollection1)", "Program.F(MyCollection2)").WithLocation(24, 17) + Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(MyCollection1)", "Program.F(MyCollection2)").WithLocation(26, 17) ); } @@ -1837,7 +1841,6 @@ static void Main() public void BetterConversionFromExpression_String_01(string spanType) { string source = $$""" - using System; using static System.Console; class Program @@ -1876,7 +1879,6 @@ static void Main() public void BetterConversionFromExpression_String_02(string spanType) { string source = $$""" - using System; using static System.Console; class Program @@ -1897,20 +1899,14 @@ static void Main() """; var comp = CreateCompilation( source, - targetFramework: TargetFramework.Net80); - comp.VerifyEmitDiagnostics( - // (13,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F1(ReadOnlySpan)' and 'Program.F1(string)' - // F1([]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F1").WithArguments($"Program.F1({spanType})", "Program.F1(string)").WithLocation(13, 9), - // (14,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F2(string)' and 'Program.F2(ReadOnlySpan)' - // F2([]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F2").WithArguments("Program.F2(string)", $"Program.F2({spanType})").WithLocation(14, 9), - // (15,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F1(ReadOnlySpan)' and 'Program.F1(string)' - // F1(['a', 'b', 'c']); - Diagnostic(ErrorCode.ERR_AmbigCall, "F1").WithArguments($"Program.F1({spanType})", "Program.F1(string)").WithLocation(15, 9), - // (16,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F2(string)' and 'Program.F2(ReadOnlySpan)' - // F2(['1', '2', '3']); - Diagnostic(ErrorCode.ERR_AmbigCall, "F2").WithArguments("Program.F2(string)", $"Program.F2({spanType})").WithLocation(16, 9)); + targetFramework: TargetFramework.Net80, + options: TestOptions.ReleaseExe); + CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput($$""" + F1({{spanType}}) + F2({{spanType}}) + F1({{spanType}}) + F2({{spanType}}) + """)); } [Theory] @@ -1919,7 +1915,6 @@ static void Main() public void BetterConversionFromExpression_String_03(string spanType) { string source = $$""" - using System; using static System.Console; class Program @@ -1938,14 +1933,12 @@ static void Main() """; var comp = CreateCompilation( source, - targetFramework: TargetFramework.Net80); - comp.VerifyEmitDiagnostics( - // (13,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F1(ReadOnlySpan)' and 'Program.F1(string)' - // F1([]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F1").WithArguments($"Program.F1({spanType})", $"Program.F1(string)").WithLocation(13, 9), - // (14,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F2(string)' and 'Program.F2(ReadOnlySpan)' - // F2([]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F2").WithArguments($"Program.F2(string)", $"Program.F2({spanType})").WithLocation(14, 9)); + targetFramework: TargetFramework.Net80, + options: TestOptions.ReleaseExe); + CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput($$""" + F1({{spanType}}) + F2({{spanType}}) + """)); } [Theory] @@ -1954,7 +1947,6 @@ static void Main() public void BetterConversionFromExpression_String_04(string spanType) { string source = $$""" - using System; using static System.Console; class MyChar @@ -1997,7 +1989,6 @@ static void Main() public void BetterConversionFromExpression_String_05() { string source = $$""" - using System; using System.Collections.Generic; using static System.Console; @@ -2013,17 +2004,10 @@ static void Main() } } """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (12,11): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // F([]); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(12, 11), - // (13,11): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // F(['a']); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(13, 11), - // (13,12): 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?) - // F(['a']); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "'a'").WithArguments("string", "Add").WithLocation(13, 12)); + CompileAndVerify(source, expectedOutput: """ + F(IEnumerable) + F(IEnumerable) + """); } [Fact] @@ -2779,21 +2763,15 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,11): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // (6,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'string' // F([], ['B']); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(6, 11), - // (7,11): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // F([default], ['B']); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[default]").WithArguments("string", "0").WithLocation(7, 11), - // (7,12): 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?) + Diagnostic(ErrorCode.ERR_BadArgType, "[]").WithArguments("1", "collection expressions", "string").WithLocation(6, 11), + // (7,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'string' // F([default], ['B']); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "default").WithArguments("string", "Add").WithLocation(7, 12), - // (8,11): error CS1729: 'string' does not contain a constructor that takes 0 arguments + Diagnostic(ErrorCode.ERR_BadArgType, "[default]").WithArguments("1", "collection expressions", "string").WithLocation(7, 11), + // (8,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'string' // F(['A'], ['B']); - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['A']").WithArguments("string", "0").WithLocation(8, 11), - // (8,12): 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?) - // F(['A'], ['B']); - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "'A'").WithArguments("string", "Add").WithLocation(8, 12)); + Diagnostic(ErrorCode.ERR_BadArgType, "['A']").WithArguments("1", "collection expressions", "string").WithLocation(8, 11)); } [Fact] @@ -3752,70 +3730,6 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionNoTargetType, "[3]").WithLocation(7, 13)); } - [Fact] - public void ListBase() - { - string sourceA = """ - using System.Collections; - namespace System - { - public class Object { } - public abstract class ValueType { } - public class String { } - public class Type { } - public struct Void { } - public struct Boolean { } - public struct Int32 { } - } - namespace System.Collections - { - public interface IEnumerable { } - } - namespace System.Collections.Generic - { - public class ListBase : IEnumerable - { - public void Add(string s) { } - } - public class List : ListBase - { - public void Add(T t) { } - } - } - """; - string sourceB = """ - using System.Collections.Generic; - class Program - { - static void Main() - { - ListBase x = []; - ListBase y = [1, 2]; - ListBase z = ["a", "b"]; - } - } - """; - var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.RegularPreview.WithNoRefSafetyRulesAttribute()); - 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,28): error CS1950: The best overloaded Add method 'ListBase.Add(string)' for the collection initializer has some invalid arguments - // ListBase y = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "1").WithArguments("System.Collections.Generic.ListBase.Add(string)").WithLocation(7, 28), - // 1.cs(7,28): error CS1503: Argument 1: cannot convert from 'int' to 'string' - // ListBase y = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "string").WithLocation(7, 28), - // 1.cs(7,31): error CS1950: The best overloaded Add method 'ListBase.Add(string)' for the collection initializer has some invalid arguments - // ListBase y = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "2").WithArguments("System.Collections.Generic.ListBase.Add(string)").WithLocation(7, 31), - // 1.cs(7,31): error CS1503: Argument 1: cannot convert from 'int' to 'string' - // ListBase y = [1, 2]; - Diagnostic(ErrorCode.ERR_BadArgType, "2").WithArguments("1", "int", "string").WithLocation(7, 31)); - - var collectionType = comp.GetWellKnownType(WellKnownType.System_Collections_Generic_List_T).Construct(comp.GetSpecialType(SpecialType.System_Int32)); - Assert.Equal(CollectionExpressionTypeKind.ImplementsIEnumerable, ConversionsBase.GetCollectionExpressionTypeKind(comp, collectionType, out _)); - } - [WorkItem("https://github.com/dotnet/roslyn/issues/69839")] [Fact] public void ListInterfaces_01() @@ -3865,6 +3779,12 @@ 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), @@ -3929,6 +3849,12 @@ 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)); @@ -4566,6 +4492,131 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[3, 4]").WithArguments("I").WithLocation(27, 13)); } + [Fact] + public void StringType_01() + { + string source = """ + class Program + { + static void Main() + { + string s; + s = []; + s = [default]; + s = [null]; + s = ['a']; + s = [1]; + s = [..""]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // s = []; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(6, 13), + // (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), + // (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,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?) + // s = ['a']; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "['a']").WithArguments("string", "Add").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,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?) + // s = [..""]; + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, @"[..""""]").WithArguments("string", "Add").WithLocation(11, 13)); + } + + [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] + [Fact] + public void StringType_02() + { + string source = """ + class Program + { + static void Main() + { + _ = (string)[]; + _ = (string)[default]; + _ = (string)[null]; + _ = (string)['a']; + _ = (string)[1]; + _ = (string)[..""]; + } + } + """; + 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 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,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,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), + // (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,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)); + } + [Fact] public void EnumType_01() { @@ -4825,9 +4876,9 @@ public void PointerType_05A() using System.Collections.Generic; class C : IEnumerable { - private List _list = new List(); - unsafe public void Add(void* p) { _list.Add((nint)p); } - IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(object o) { } + unsafe public void Add(void* p) { } + IEnumerator IEnumerable.GetEnumerator() => null; } class Program { @@ -5228,47 +5279,31 @@ struct S { } [Fact] public void CollectionInitializerType_03() { - string source = """ + string sourceA = """ using System.Collections; - S s; - s = []; struct S : IEnumerable { - IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() { yield break; } } """; - CompileAndVerify(source, expectedOutput: ""); - - source = """ - using System.Collections; + string sourceB1 = """ S s; - s = [1, 2]; - struct S : IEnumerable - { - IEnumerator IEnumerable.GetEnumerator() => throw null; - } + s = []; + s.Report(); """; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics( - // (3,6): 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").WithArguments("S", "Add").WithLocation(3, 6), - // (3,9): 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, "2").WithArguments("S", "Add").WithLocation(3, 9)); + CompileAndVerify(new[] { sourceA, sourceB1, s_collectionExtensions }, expectedOutput: "[], "); - source = """ - using System.Collections; + string sourceB2 = """ S s; + s = [1, 2]; s = [.. new object()]; - struct S : IEnumerable - { - IEnumerator IEnumerable.GetEnumerator() => throw null; - } """; - comp = CreateCompilation(source); + var comp = CreateCompilation(new[] { sourceA, sourceB2 }); comp.VerifyEmitDiagnostics( - // (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' + // 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(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)); } @@ -5295,9 +5330,16 @@ 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)); + 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)); } + [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] [Fact] public void CollectionInitializerType_05() { @@ -5315,19 +5357,23 @@ public void Add(int i) { } class B { static A Create2() => [1, 2]; + static object Create3() => (A)[]; } """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( // (13,27): error CS0122: 'A.A()' is inaccessible due to its protection level // static A Create2() => [1, 2]; - Diagnostic(ErrorCode.ERR_BadAccess, "[1, 2]").WithArguments("A.A()").WithLocation(13, 27)); + Diagnostic(ErrorCode.ERR_BadAccess, "[1, 2]").WithArguments("A.A()").WithLocation(13, 27), + // (14,35): error CS0122: 'A.A()' is inaccessible due to its protection level + // static object Create3() => (A)[]; + Diagnostic(ErrorCode.ERR_BadAccess, "[]").WithArguments("A.A()").WithLocation(14, 35)); } [Fact] public void CollectionInitializerType_06() { - string source = """ + string sourceA = """ using System.Collections; using System.Collections.Generic; class C : IEnumerable @@ -5336,6 +5382,8 @@ class C : IEnumerable public void Add(T t) { _list.Add(t); } IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } + """; + string sourceB1 = """ class Program { static void Main() @@ -5346,14 +5394,31 @@ static void Main() o = (C)[]; c.Report(); o.Report(); + } + } + """; + CompileAndVerify(new[] { sourceA, sourceB1, s_collectionExtensions }, expectedOutput: "[], [], "); + + string sourceB2 = """ + class Program + { + static void Main() + { + C c; + object o; c = [1, 2]; o = (C)[3, 4]; - c.Report(); - o.Report(); } } """; - CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [], [1, 2], [3, 4], "); + 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)); } [Fact] @@ -5453,18 +5518,52 @@ static void Main() Diagnostic(ErrorCode.ERR_NoNewAbstract, "[]").WithArguments("A").WithLocation(14, 15)); } + [WorkItem("https://github.com/dotnet/roslyn/pull/71492")] [Fact] - public void CollectionInitializerType_08() + 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; } + class Program + { + static void M0() + { + object o = (S0)[]; + o = (S0)[1, 2]; + S0 s = []; + s = [1, 2]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_08B() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; struct S1 : IEnumerable { public void Add(T t) { } @@ -5480,11 +5579,6 @@ public void Add(T t) { } } class Program { - static void M0() - { - object o = (S0)[]; - S0 s = [1, 2]; - } static void M1() { object o = (S1)[]; @@ -5498,26 +5592,6 @@ static void M2() } """; var verifier = CompileAndVerify(source); - verifier.VerifyIL("Program.M0", """ - { - // Code size 35 (0x23) - .maxstack 2 - .locals init (S0 V_0) - IL_0000: ldloca.s V_0 - IL_0002: initobj "S0" - IL_0008: ldloc.0 - IL_0009: pop - IL_000a: ldloca.s V_0 - IL_000c: initobj "S0" - IL_0012: ldloca.s V_0 - IL_0014: ldc.i4.1 - IL_0015: call "void S0.Add(int)" - IL_001a: ldloca.s V_0 - IL_001c: ldc.i4.2 - IL_001d: call "void S0.Add(int)" - IL_0022: ret - } - """); verifier.VerifyIL("Program.M1", """ { // Code size 35 (0x23) @@ -5681,7 +5755,7 @@ static void Main() } [Fact] - public void CollectionInitializerType_13() + public void CollectionInitializerType_13A() { string source = """ using System.Collections; @@ -5704,67 +5778,197 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,36): error CS0121: The call is ambiguous between the following methods or properties: 'C.Add(IA)' and 'C.Add(IB)' + // (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)'. + // 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_AmbigCall, "new AB()").WithArguments("C.Add(IA)", "C.Add(IB)").WithLocation(15, 36)); + Diagnostic(ErrorCode.ERR_BadArgType, "[(IA)null, (IB)null, new AB()]").WithArguments("1", "object", "IA").WithLocation(15, 15)); } [Fact] - public void CollectionInitializerType_14() + public void CollectionInitializerType_13B() { string source = """ using System.Collections; - struct S : IEnumerable + interface IA { } + interface IB { } + class AB : IA, IB { } + class C : IEnumerable { - public void Add(T x, T y) { } - IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => null; + } + static class Extensions + { + public static void Add(this C c, IA a) { } + public static void Add(this C c, IB b) { } } class Program { static void Main() { - S s; - s = []; - s = [1, 2]; + C c = [(IA)null, (IB)null, new AB()]; } } """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (13,14): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' - // s = [1, 2]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "1").WithArguments("y", "S.Add(int, int)").WithLocation(13, 14), - // (13,17): error CS7036: There is no argument given that corresponds to the required parameter 'y' of 'S.Add(int, int)' - // s = [1, 2]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "2").WithArguments("y", "S.Add(int, int)").WithLocation(13, 17)); + // (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' + // 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)); } [Fact] - public void CollectionInitializerType_15() + public void CollectionInitializerType_14A() { string source = """ using System.Collections; - using System.Collections.Generic; - class C : IEnumerable + struct S : IEnumerable { - List _list = new List(); - public void Add(T t, int index = -1) { _list.Add(t); } - IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + public void Add(T x, T y) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; } class Program { static void Main() { - C c = [1, 2]; - c.Report(); + S s; + s = []; + s = [1, ..s]; } } """; - CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[1, 2], "); + 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)'. + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("object", "S.Add(int, int)").WithLocation(13, 13)); + } + + [Fact] + public void CollectionInitializerType_14B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct S : IEnumerable + { + public void Add(T x, T y) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class Program + { + static void Main() + { + S s; + s = []; + s = [1, ..s]; + } + } + """; + 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)'. + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("int", "S.Add(int, int)").WithLocation(15, 13)); + } + + [Fact] + public void CollectionInitializerType_14C() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct S : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class Extensions + { + public static void Add(this S s, T x, T y) { } + } + class Program + { + static void Main() + { + S s; + s = []; + s = [1, ..s]; + } + } + """; + 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)'. + // s = [1, ..s]; + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[1, ..s]").WithArguments("int", "Extensions.Add(S, T, T)").WithLocation(18, 13)); + } + + [Fact] + public void CollectionInitializerType_15A() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class C : IEnumerable + { + List _list = new List(); + public void Add(T t, int index = -1) { _list.Add(t); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + C c = []; + c = [1, 2]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_15B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class C : IEnumerable + { + List _list = new List(); + public void Add(T t, int index = -1) { _list.Add(t); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + C c = []; + c.Report(); + c = [1, 2]; + c.Report(); + } + } + """; + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [1, 2], "); } [Fact] - public void CollectionInitializerType_16() + public void CollectionInitializerType_16A() { string source = """ using System.Collections; @@ -5779,12 +5983,46 @@ class Program { static void Main() { - C c = [1, 2]; + C c = []; + c = [1, 2]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_16B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class C : IEnumerable + { + List _list = new List(); + public void Add(T t, params T[] args) { _list.Add(t); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + C c = []; + c.Report(); + c = [1, 2]; c.Report(); } } """; - CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[1, 2], "); + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], [1, 2], "); } [Fact] @@ -5793,10 +6031,11 @@ public void CollectionInitializerType_17() string sourceA = """ using System.Collections; using System.Collections.Generic; - class C : IEnumerable + class C : IEnumerable { List _list = new List(); public void Add(params T[] args) { _list.AddRange(args); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } """; @@ -5813,12 +6052,12 @@ static void Main() """; var comp = CreateCompilation(new[] { sourceA, sourceB1, s_collectionExtensions }); comp.VerifyEmitDiagnostics( - // 1.cs(5,21): error CS9174: Cannot initialize type 'object' with a collection expression because the type is not constructible. + // 1.cs(5,21): error CS9174: Cannot initialize type 'int' with a collection expression because the type is not constructible. // C c = [[], [1, 2]]; - Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("object").WithLocation(5, 21), - // 1.cs(5,25): error CS9174: Cannot initialize type 'object' with a collection expression because the type is not constructible. + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("int").WithLocation(5, 21), + // 1.cs(5,25): error CS9174: Cannot initialize type 'int' with a collection expression because the type is not constructible. // C c = [[], [1, 2]]; - Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[1, 2]").WithArguments("object").WithLocation(5, 25)); + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[1, 2]").WithArguments("int").WithLocation(5, 25)); string sourceB2 = """ class Program @@ -5855,7 +6094,7 @@ .locals init (C V_0) } [Fact] - public void CollectionInitializerType_18() + public void CollectionInitializerType_18A() { string source = """ using System.Collections; @@ -5873,16 +6112,119 @@ class Program """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (11,50): error CS1950: The best overloaded Add method 'S.Add(T)' for the collection initializer has some invalid arguments + // (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)'. // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "y").WithArguments("S.Add(T)").WithLocation(11, 50), - // (11,50): error CS1503: Argument 1: cannot convert from 'U' to 'T' + 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' // static S Create(T x, U y) => [x, y]; - Diagnostic(ErrorCode.ERR_BadArgType, "y").WithArguments("1", "U", "T").WithLocation(11, 50)); + Diagnostic(ErrorCode.ERR_BadArgType, "[x, y]").WithArguments("1", "object", "T").WithLocation(11, 46)); } [Fact] - public void CollectionInitializerType_19() + public void CollectionInitializerType_18B() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class S : IEnumerable + { + internal void Add(T t) { } + private void Add(U u) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + static S Create(T t, U u) => [t, u]; + } + class Program + { + static S Create(T x, U y) => [x, y]; + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (9,44): error CS0029: Cannot implicitly convert type 'U' to 'T' + // static S Create(T t, U u) => [t, u]; + Diagnostic(ErrorCode.ERR_NoImplicitConv, "u").WithArguments("U", "T").WithLocation(9, 44), + // (13,50): error CS0029: Cannot implicitly convert type 'U' to 'T' + // static S Create(T x, U y) => [x, y]; + Diagnostic(ErrorCode.ERR_NoImplicitConv, "y").WithArguments("U", "T").WithLocation(13, 50)); + } + + [Fact] + public void CollectionInitializerType_18C() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class S : IEnumerable + { + internal void Add(T t) { } + private void Add(U u) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + static S Create(T t, U u) => [t, u]; + } + class Program + { + static S Create(T x, U y) => [x, y]; + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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)); + } + + [Fact] + public void CollectionInitializerType_18D() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + abstract class A : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class B : A, IEnumerable + { + internal void Add(T t) { } + private void Add(U u) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + static B Create(T t, U u) => [t, u]; + } + class Program + { + static B Create(T x, U y) => [x, y]; + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (13,40): error CS9213: Collection expression target 'B' has no element type. + // static B Create(T t, U u) => [t, u]; + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetNoElementType, "[t, u]").WithArguments("B").WithLocation(13, 40), + // (17,46): error CS9213: Collection expression target 'B' has no element type. + // static B Create(T x, U y) => [x, y]; + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetNoElementType, "[x, y]").WithArguments("B").WithLocation(17, 46)); + } + + [Fact] + public void CollectionInitializerType_19A() { string source = """ class Program @@ -5903,9 +6245,37 @@ 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,14): 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 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)); + } + + [Fact] + public void CollectionInitializerType_19B() + { + string source = """ + class Program + { + static void Main() + { + string s; + s = []; + s = ['a']; + } + } + static class E + { + internal static void Add(this string s, char c) { } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // s = []; + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(6, 13), + // (7,13): error CS1729: 'string' does not contain a constructor that takes 0 arguments // s = ['a']; - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "'a'").WithArguments("string", "Add").WithLocation(7, 14)); + Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['a']").WithArguments("string", "0").WithLocation(7, 13)); } [Fact] @@ -5996,6 +6366,653 @@ static MyCollection Create(string x, int[] y, double[] z) """); } + [Fact] + public void CollectionInitializerType_InaccessibleConstructor() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private MyCollection() { } + public void Add(T t) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + static MyCollection _x = []; + static MyCollection _y = [default, .._x]; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (16,31): error CS0122: 'MyCollection.MyCollection()' is inaccessible due to its protection level + // MyCollection x = []; + Diagnostic(ErrorCode.ERR_BadAccess, "[]").WithArguments("MyCollection.MyCollection()").WithLocation(16, 31), + // (17,31): error CS0122: 'MyCollection.MyCollection()' is inaccessible due to its protection level + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_BadAccess, "[1, ..x]").WithArguments("MyCollection.MyCollection()").WithLocation(17, 31)); + } + + [Fact] + public void CollectionInitializerType_InaccessibleAdd() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private void Add(T t) { } + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + static MyCollection _x = []; + static MyCollection _y = [default, .._x]; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_InaccessibleExtensionAdd() + { + string sourceA = """ + using System.Collections; + using System.Collections.Generic; + public class MyCollection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + static MyCollection _x = []; + static MyCollection _y = [default, .._x]; + } + public static class Extensions + { + internal static void Add(this MyCollection c, T t) { } + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.ToMetadataReference(); + + string sourceB = """ + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_AddByValue() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + private List _list = new(); + public MyCollection() { } + public void Add(T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + CompileAndVerify(source, expectedOutput: "1, 3, "); + } + + [Fact] + public void CollectionInitializerType_AddByRef_Out() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + public void Add(out T t) => throw null; + public IEnumerator GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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)); + } + + [Fact] + public void CollectionInitializerType_AddByRef_Ref() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + public void Add(ref T t) { } + public IEnumerator GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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)); + } + + [Fact] + public void CollectionInitializerType_AddByRef_In() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private List _list = new(); + public void Add(in T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + CompileAndVerify(source, expectedOutput: "1, 3, "); + } + + [Fact] + public void CollectionInitializerType_AddByRef_RefReadonly() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + class MyCollection : IEnumerable + { + private List _list = new(); + public void Add(ref readonly T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + int v = 4; + MyCollection z = [..x, ..y, 3, v]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + var comp = CreateCompilation(source, options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics( + // (14,42): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter + // MyCollection x = new() { 1 }; + Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "1").WithArguments("1").WithLocation(14, 42), + // (17,35): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter + // MyCollection z = [..x, ..y, 3, v]; + Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "..x").WithArguments("1").WithLocation(17, 35), + // (17,40): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter + // MyCollection z = [..x, ..y, 3, v]; + Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "..y").WithArguments("1").WithLocation(17, 40), + // (17,45): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter + // MyCollection z = [..x, ..y, 3, v]; + Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "3").WithArguments("1").WithLocation(17, 45)); + CompileAndVerify(comp, expectedOutput: "1, 3, 4, "); + } + + [Fact] + public void CollectionInitializerType_AddByValue_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + private List _list = new(); + public MyCollection() { } + internal void AddValue(T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + static class Extensions + { + public static void Add(this ref MyCollection c, T t) { c.AddValue(t); } + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + CompileAndVerify(source, expectedOutput: "1, 3, "); + } + + [Fact] + public void CollectionInitializerType_AddByRef_Out_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + } + static class Extensions + { + public static void Add(this ref MyCollection c, out T t) => throw null; + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, out object)").WithLocation(18, 34)); + } + + [Fact] + public void CollectionInitializerType_AddByRef_Ref_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + } + static class Extensions + { + public static void Add(this ref MyCollection c, ref T t) => throw null; + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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. + // MyCollection z = [..x, ..y, 3]; + Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "[..x, ..y, 3]").WithArguments("Extensions.Add(ref MyCollection, ref object)").WithLocation(18, 34)); + } + + [Fact] + public void CollectionInitializerType_AddByRef_In_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + private List _list = new(); + public MyCollection() { } + internal void AddValue(T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + static class Extensions + { + public static void Add(this ref MyCollection c, in T t) { c.AddValue(t); } + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + CompileAndVerify(source, expectedOutput: "1, 3, "); + } + + [Fact] + public void CollectionInitializerType_AddByRef_RefReadonly_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + private List _list = new(); + public MyCollection() { } + internal void AddValue(T t) { _list.Add(t); } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } + static class Extensions + { + public static void Add(this ref MyCollection c, ref readonly T t) { c.AddValue(t); } + } + class Program + { + static void Main() + { + MyCollection x = new() { 1 }; + MyCollection y = []; + MyCollection z = [..x, ..y, 3]; + foreach (var i in z) + System.Console.Write("{0}, ", i); + } + } + """; + CompileAndVerify(source, expectedOutput: "1, 3, "); + } + + [Fact] + public void CollectionInitializerType_InvalidParameterByValue_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class Extensions + { + public static void Add(this ref MyCollection c, string s) { } + } + class Program + { + static void Main() + { + MyCollection x; + x = new() { "1" }; + x = ["2"]; + MyCollection y; + y = new() { 3 }; + y = [4]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (20,21): error CS1950: The best overloaded Add method 'Extensions.Add(ref MyCollection, string)' for the collection initializer has some invalid arguments + // y = new() { 3 }; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "3").WithArguments("Extensions.Add(ref MyCollection, string)").WithLocation(20, 21), + // (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)'. + // 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' + // y = [4]; + Diagnostic(ErrorCode.ERR_BadArgType, "[4]").WithArguments("2", "int", "string").WithLocation(21, 13)); + } + + [Fact] + public void CollectionInitializerType_InvalidParameterByRef_Extension() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + static class Extensions + { + public static void Add(this ref MyCollection c, ref string s) { } + } + class Program + { + static void Main() + { + MyCollection x; + x = new() { "1" }; + x = ["2"]; + MyCollection y; + y = new() { 3 }; + y = [4]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (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), + // (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)); + } + + [Fact] + public void CollectionInitializerType_WrongSignature() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + public static void Add(T t) { } + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + 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)); + } + + [Fact] + public void CollectionInitializerType_ObsoleteAdd_01() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + [Obsolete] public void Add(T t) { } + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): warning CS1064: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "1").WithArguments("MyCollection.Add(int)").WithLocation(15, 32), + // (15,37): warning CS1064: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAdd, "x").WithArguments("MyCollection.Add(int)").WithLocation(15, 37)); + } + + [Fact] + public void CollectionInitializerType_ObsoleteAdd_02() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + [Obsolete("do not use")] public void Add(T t) { } + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): warning CS1062: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. do not use + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAddStr, "1").WithArguments("MyCollection.Add(int)", "do not use").WithLocation(15, 32), + // (15,37): warning CS1062: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. do not use + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.WRN_DeprecatedCollectionInitAddStr, "x").WithArguments("MyCollection.Add(int)", "do not use").WithLocation(15, 37)); + } + + [Fact] + public void CollectionInitializerType_ObsoleteAdd_03() + { + string source = """ + using System; + using System.Collections; + using System.Collections.Generic; + struct MyCollection : IEnumerable + { + [Obsolete("do not use", error: true)] public void Add(T t) { } + public IEnumerator GetEnumerator() => throw null; + IEnumerator IEnumerable.GetEnumerator() => throw null; + } + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, ..x]; + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (15,32): error CS1063: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. do not use + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_DeprecatedCollectionInitAddStr, "1").WithArguments("MyCollection.Add(int)", "do not use").WithLocation(15, 32), + // (15,37): error CS1063: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer element is obsolete. do not use + // MyCollection y = [1, ..x]; + Diagnostic(ErrorCode.ERR_DeprecatedCollectionInitAddStr, "x").WithArguments("MyCollection.Add(int)", "do not use").WithLocation(15, 37)); + } + [Fact] public void CollectionInitializerType_Dynamic_01() { @@ -6726,7 +7743,7 @@ public void TypeParameter_01(string type) using System; using System.Collections; using System.Collections.Generic; - interface I : IEnumerable + interface I : IEnumerable { void Add(T t); } @@ -6737,6 +7754,10 @@ public void Add(T t) { GetList().Add(t); } + IEnumerator IEnumerable.GetEnumerator() + { + return GetList().GetEnumerator(); + } IEnumerator IEnumerable.GetEnumerator() { return GetList().GetEnumerator(); @@ -6917,7 +7938,7 @@ public void TypeParameter_04() using System.Collections; interface IAdd : IEnumerable { - void Add(int i); + void Add(object o); } class Program { @@ -6978,17 +7999,19 @@ public class A2 { } string sourceB = """ using System.Collections; using System.Collections.Generic; - public class B1 : IEnumerable + public class B1 : IEnumerable { List _list = new List(); public B1(A1 a = null) { } public void Add(int i) { _list.Add(i); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } - public class B2 : IEnumerable + public class B2 : IEnumerable { List _list = new List(); public void Add(int x, A2 y = null) { _list.Add(x); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } """; @@ -7023,12 +8046,9 @@ static void Main() // 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'. // 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,14): 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'. - // 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 'a897d975-a839-4fff-828b-deccf9495adc, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. + // 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'. // 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_NoTypeDef, "[3, 4]").WithArguments("A2", $"{assemblyA}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(13, 13)); } [Fact] @@ -7038,11 +8058,12 @@ public void ConditionalAdd_01() using System.Collections; using System.Collections.Generic; using System.Diagnostics; - class C : IEnumerable + class C : IEnumerable { List _list = new List(); - [Conditional("DEBUG")] internal void Add(T t) { _list.Add(t); } + [Conditional("DEBUG")] internal void Add(object o) { _list.Add(o); } internal void Add(U u) { _list.Add(u); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } class Program @@ -7066,11 +8087,12 @@ public void ConditionalAdd_02() using System.Collections; using System.Collections.Generic; using System.Diagnostics; - class C : IEnumerable + class C : IEnumerable { List _list = new List(); - [Conditional("DEBUG")] internal void Add(T t) { _list.Add(t); } + [Conditional("DEBUG")] internal void Add(object o) { _list.Add(o); } internal void Add(U u) { _list.Add(u); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } class Program @@ -7100,6 +8122,24 @@ static void Main() { Dictionary d; d = []; + d.Report(); + } + } + """; + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[], "); + } + + [Fact] + public void DictionaryElement_02() + { + string source = """ + using System.Collections.Generic; + class Program + { + static void Main() + { + Dictionary d; + d = [default]; d = [new KeyValuePair(1, 2)]; d = [3:4]; } @@ -7107,9 +8147,12 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (8,14): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(int, int)' + // (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)'. + // 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)'. // d = [new KeyValuePair(1, 2)]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "new KeyValuePair(1, 2)").WithArguments("value", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(8, 14), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, "[new KeyValuePair(1, 2)]").WithArguments("System.Collections.Generic.KeyValuePair", "System.Collections.Generic.Dictionary.Add(int, int)").WithLocation(8, 13), // (9,15): error CS1003: Syntax error, ',' expected // d = [3:4]; Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",").WithLocation(9, 15), @@ -8208,42 +9251,18 @@ static void Main() if (targetElementType == "int") { comp.VerifyEmitDiagnostics( - // 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_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, "..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 + // 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)'. // 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' + 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' // 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 + 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)'. // c = [..(dynamic)x, ..(IEnumerable)y]; - 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' + 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' // c = [..(dynamic)x, ..(IEnumerable)y]; - 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)); + Diagnostic(ErrorCode.ERR_BadArgType, "[..(dynamic)x, ..(IEnumerable)y]").WithArguments("1", "object", "int").WithLocation(14, 13)); } else { @@ -12157,6 +13176,7 @@ public void SemanticModel() using System.Collections.Generic; struct S1 : IEnumerable { + public void Add(object o) { } IEnumerator IEnumerable.GetEnumerator() => throw null; } struct S2 @@ -12183,12 +13203,12 @@ static void Main() """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (20,17): error CS9174: Cannot initialize type 'S2' with a collection expression because the type is not constructible. + // (21,17): error CS9174: Cannot initialize type 'S2' with a collection expression because the type is not constructible. // S2 v6 = []; - Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("S2").WithLocation(20, 17), - // (26,24): error CS9174: Cannot initialize type 'S2' with a collection expression because the type is not constructible. + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("S2").WithLocation(21, 17), + // (27,24): error CS9174: Cannot initialize type 'S2' with a collection expression because the type is not constructible. // var v12 = (S2)([]); - Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("S2").WithLocation(26, 24)); + Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[]").WithArguments("S2").WithLocation(27, 24)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -13857,6 +14877,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,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)); @@ -14364,12 +15387,12 @@ static void Main() """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // 0.cs(7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters + // (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), - // 0.cs(27,42): 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 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, 42)); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[default]").WithArguments("Container.MyCollection", "Add").WithLocation(27, 41)); } [CombinatorialData] @@ -15149,9 +16172,9 @@ static void Main() """; comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (6,27): 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 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, 27)); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[2]").WithArguments("MyCollection", "Add").WithLocation(6, 26)); } [CombinatorialData] @@ -15261,21 +16284,15 @@ static void Main() new[] { sourceA, sourceB2 }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // 1.cs(5,26): error CS7036: There is no argument given that corresponds to the required parameter 'list' of 'MyCollection.MyCollection(List)' + // 1.cs(5,26): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection x = []; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[]").WithArguments("list", "MyCollection.MyCollection(System.Collections.Generic.List)").WithLocation(5, 26), - // 1.cs(6,26): error CS7036: There is no argument given that corresponds to the required parameter 'list' of 'MyCollection.MyCollection(List)' + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[]").WithLocation(5, 26), + // 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_NoCorrespondingArgument, "[1, 2, 3]").WithArguments("list", "MyCollection.MyCollection(System.Collections.Generic.List)").WithLocation(6, 26), - // 1.cs(6,27): 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?) + 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").WithArguments("MyCollection", "Add").WithLocation(6, 27), - // 1.cs(6,30): 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, "2").WithArguments("MyCollection", "Add").WithLocation(6, 30), - // 1.cs(6,33): 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, "3").WithArguments("MyCollection", "Add").WithLocation(6, 33)); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, 3]").WithArguments("MyCollection", "Add").WithLocation(6, 26)); } [Fact] @@ -15338,21 +16355,15 @@ static void Main() new[] { sourceA, sourceB2 }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // 1.cs(5,34): error CS7036: There is no argument given that corresponds to the required parameter 'list' of 'MyCollection.MyCollection(List)' + // 1.cs(5,34): error CS9214: Collection expression type must have an applicable constructor that can be called with no arguments. // MyCollection x = []; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[]").WithArguments("list", "MyCollection.MyCollection(System.Collections.Generic.List)").WithLocation(5, 34), - // 1.cs(6,34): error CS7036: There is no argument given that corresponds to the required parameter 'list' of 'MyCollection.MyCollection(List)' - // MyCollection y = [1, 2, null]; - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "[1, 2, null]").WithArguments("list", "MyCollection.MyCollection(System.Collections.Generic.List)").WithLocation(6, 34), - // 1.cs(6,35): 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").WithArguments("MyCollection", "Add").WithLocation(6, 35), - // 1.cs(6,38): 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?) + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[]").WithLocation(5, 34), + // 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_NoSuchMemberOrExtension, "2").WithArguments("MyCollection", "Add").WithLocation(6, 38), - // 1.cs(6,41): 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?) + 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, "null").WithArguments("MyCollection", "Add").WithLocation(6, 41)); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "[1, 2, null]").WithArguments("MyCollection", "Add").WithLocation(6, 34)); } [Fact] @@ -16445,6 +17456,7 @@ class Program static void Main() { F([]); + F([null]); F(new()); } static void F(Container.MyCollection c) @@ -16454,9 +17466,12 @@ static void F(Container.MyCollection c) """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // 0.cs(7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters + // (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)); + Diagnostic(ErrorCode.ERR_AttrArgWithTypeVars, "typeof(MyCollectionBuilder)").WithArguments("Container.MyCollectionBuilder").WithLocation(7, 24), + // (24,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'Container.MyCollection' + // F([null]); + Diagnostic(ErrorCode.ERR_BadArgType, "[null]").WithArguments("1", "collection expressions", "Container.MyCollection").WithLocation(24, 11)); var collectionType = (NamedTypeSymbol)comp.GetMember("Program.F").Parameters[0].Type; Assert.Equal("Container.MyCollection", collectionType.ToTestDisplayString()); @@ -17288,15 +18303,9 @@ static class MyCollectionBuilder """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( - // (6,49): error CS1729: 'string' does not contain a constructor that takes 0 arguments - // [CollectionBuilder(typeof(MyCollectionBuilder), ['h', 'i'])] - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "['h', 'i']").WithArguments("string", "0").WithLocation(6, 49), - // (6,50): 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,49): error CS1503: Argument 2: cannot convert from 'collection expressions' to 'string' // [CollectionBuilder(typeof(MyCollectionBuilder), ['h', 'i'])] - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "'h'").WithArguments("string", "Add").WithLocation(6, 50), - // (6,55): 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?) - // [CollectionBuilder(typeof(MyCollectionBuilder), ['h', 'i'])] - Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "'i'").WithArguments("string", "Add").WithLocation(6, 55)); + Diagnostic(ErrorCode.ERR_BadArgType, "['h', 'i']").WithArguments("2", "collection expressions", "string").WithLocation(6, 49)); } [Fact] @@ -22369,7 +23378,7 @@ public void ExpressionTrees() using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; - interface I : IEnumerable + interface I : IEnumerable { void Add(T t); } @@ -23300,9 +24309,11 @@ public void IOperation_NullableConversion() { string source = """ using System.Collections; - struct MyCollection : IEnumerable + using System.Collections.Generic; + struct MyCollection : IEnumerable { public void Add(T t) { } + IEnumerator IEnumerable.GetEnumerator() => null; IEnumerator IEnumerable.GetEnumerator() => null; } class Program @@ -23538,17 +24549,18 @@ public void IOperation_SpreadElement_NoConversion_01() string source = """ using System.Collections; using System.Collections.Generic; - class MyCollection : IEnumerable + class MyCollection : IEnumerable { - private List _list = new(); + private List _list = new(); public void Add(int i) { _list.Add(i); } + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } class Program { static void Main() { - MyCollection x = [1]; + IEnumerable x = new int[] { 1 }; MyCollection y = /**/[..x]/**/; } } @@ -23556,20 +24568,17 @@ static void Main() var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (14,37): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // (15,39): error CS0029: Cannot implicitly convert type 'object' to 'int' // MyCollection y = /**/[..x]/**/; - Diagnostic(ErrorCode.ERR_BadArgType, "..x").WithArguments("1", "object", "int").WithLocation(14, 37), - // (14,39): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments - // MyCollection y = /**/[..x]/**/; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(int)").WithLocation(14, 39)); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("object", "int").WithLocation(15, 39)); VerifyOperationTreeForTest(comp, """ - ICollectionExpressionOperation (1 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[..x]') + ICollectionExpressionOperation (1 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[..x]') Elements(1): ISpreadOperation (ElementType: System.Object) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..x') Operand: - ILocalReferenceOperation: x (OperationKind.LocalReference, Type: MyCollection, IsInvalid) (Syntax: 'x') + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Collections.IEnumerable, IsInvalid) (Syntax: 'x') ElementConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) (NoConversion) """); @@ -23581,18 +24590,18 @@ public void IOperation_SpreadElement_NoConversion_02() string source = """ using System.Collections; using System.Collections.Generic; - class MyCollection : IEnumerable + class MyCollection : IEnumerable { - private List _list = new(); + private List _list = new(); public void Add(int i) { _list.Add(i); } - IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); } class Program { static void Main() { - MyCollection x = [1]; + IEnumerable x = new object[] { 1 }; MyCollection y = /**/[..x]/**/; } } @@ -23600,20 +24609,17 @@ static void Main() var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (15,37): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // (15,39): error CS0029: Cannot implicitly convert type 'object' to 'int' // MyCollection y = /**/[..x]/**/; - Diagnostic(ErrorCode.ERR_BadArgType, "..x").WithArguments("1", "object", "int").WithLocation(15, 37), - // (15,39): error CS1950: The best overloaded Add method 'MyCollection.Add(int)' for the collection initializer has some invalid arguments - // MyCollection y = /**/[..x]/**/; - Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "x").WithArguments("MyCollection.Add(int)").WithLocation(15, 39)); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("object", "int").WithLocation(15, 39)); VerifyOperationTreeForTest(comp, """ - ICollectionExpressionOperation (1 elements, ConstructMethod: MyCollection..ctor()) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[..x]') + ICollectionExpressionOperation (1 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: MyCollection, IsInvalid) (Syntax: '[..x]') Elements(1): ISpreadOperation (ElementType: System.Object) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '..x') Operand: - ILocalReferenceOperation: x (OperationKind.LocalReference, Type: MyCollection, IsInvalid) (Syntax: 'x') + ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Collections.Generic.IEnumerable, IsInvalid) (Syntax: 'x') ElementConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) (NoConversion) """); @@ -23636,13 +24642,15 @@ .. GetConfig(), var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,12): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'Dictionary.Add(string, object)' - // .. GetConfig(), - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetConfig()").WithArguments("value", "System.Collections.Generic.Dictionary.Add(string, object)").WithLocation(5, 12)); + // (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)'. + // Dictionary Config => /**/[ + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingAdd, @"[ + .. GetConfig(), + ]").WithArguments("System.Collections.Generic.KeyValuePair", "System.Collections.Generic.Dictionary.Add(string, object)").WithLocation(4, 52)); VerifyOperationTreeForTest(comp, """ - ICollectionExpressionOperation (1 elements, ConstructMethod: System.Collections.Generic.Dictionary..ctor()) (OperationKind.CollectionExpression, Type: System.Collections.Generic.Dictionary, IsInvalid) (Syntax: '[ ... ]') + ICollectionExpressionOperation (1 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: System.Collections.Generic.Dictionary, IsInvalid) (Syntax: '[ ... ]') Elements(1): ISpreadOperation (ElementType: System.Collections.Generic.KeyValuePair) (OperationKind.Spread, Type: null, IsInvalid) (Syntax: '.. GetConfig()') Operand: @@ -23794,11 +24802,10 @@ static void Main(List list) } } """; - // There's now a conversion from [] to string CreateCompilation(source).VerifyEmitDiagnostics( - // (7,9): error CS1729: 'string' does not contain a constructor that takes 0 arguments + // (7,9): error CS0019: Operator '+' cannot be applied to operands of type 'collection expressions' and 'List' // [] + list; - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "[]").WithArguments("string", "0").WithLocation(7, 9), + Diagnostic(ErrorCode.ERR_BadBinaryOps, "[] + list").WithArguments("+", "collection expressions", "System.Collections.Generic.List").WithLocation(7, 9), // (7,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // [] + list; Diagnostic(ErrorCode.ERR_IllegalStatement, "[] + list").WithLocation(7, 9)); @@ -24360,7 +25367,7 @@ public void MissingCtor_GenericIEnumerable() using System.Collections.Generic; C x = [1]; // 1 - C.M([1]); // 2 + C.M([1]); class C : IEnumerable { @@ -24375,28 +25382,24 @@ public static void M(int[] i) { } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (4,7): error CS7036: There is no argument given that corresponds to the required parameter 's' of 'C.C(string)' + // (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_NoCorrespondingArgument, "[1]").WithArguments("s", "C.C(string)").WithLocation(4, 7), - // (5,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(C)' and 'C.M(int[])' - // C.M([1]); // 2 - Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(5, 3) - ); + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[1]").WithLocation(4, 7)); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); var conversion1 = model.GetConversion(collections[0]); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); - // Valid identity conversion matches the behavior for an ambiguous call - // with a switch expression argument: C.M(2 switch { _ => default }); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); - Assert.True(conversion2.IsIdentity); - Assert.Null(model.GetTypeInfo(collections[1]).Type); + Assert.True(conversion2.IsCollectionExpression); + var typeInfo2 = model.GetTypeInfo(collections[1]); + Assert.Null(typeInfo2.Type); + Assert.Equal("System.Int32[]", typeInfo2.ConvertedType.ToTestDisplayString()); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24408,7 +25411,7 @@ public void MissingCtor_GenericIEnumerable_Spread() int[] values = new int[] { 1 }; C x = [..values]; // 1 - C.M([..values]); // 2 + C.M([..values]); class C : IEnumerable { @@ -24423,24 +25426,68 @@ public static void M(int[] i) { } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (5,7): error CS7036: There is no argument given that corresponds to the required parameter 's' of 'C.C(string)' + // (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_NoCorrespondingArgument, "[..values]").WithArguments("s", "C.C(string)").WithLocation(5, 7), + Diagnostic(ErrorCode.ERR_CollectionExpressionMissingConstructor, "[..values]").WithLocation(5, 7)); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); + + var conversion1 = model.GetConversion(collections[0]); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); + + var conversion2 = model.GetConversion(collections[1]); + Assert.True(conversion2.IsValid); + Assert.True(conversion2.IsCollectionExpression); + var typeInfo2 = model.GetTypeInfo(collections[1]); + Assert.Null(typeInfo2.Type); + Assert.Equal("System.Int32[]", typeInfo2.ConvertedType.ToTestDisplayString()); + } + + [Fact] + public void OverloadResolution_Ambiguity() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + + int[] values = new int[] { 1 }; + C.M([1]); // 1 + C.M([..values]); // 2 + + class C : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; + public void Add(int i) { } + + public static void M(C c) { } + public static void M(int[] i) { } + } + """; + + var comp = CreateCompilation(source).VerifyEmitDiagnostics( + // (5,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(C)' and 'C.M(int[])' + // C.M([1]); // 1 + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(5, 3), // (6,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(C)' and 'C.M(int[])' // C.M([..values]); // 2 - Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(6, 3) - ); + Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(6, 3)); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); + // Valid identity conversion matches the behavior for an ambiguous call + // with a switch expression argument: C.M(2 switch { _ => default }); + var conversion1 = model.GetConversion(collections[0]); Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.True(conversion1.IsIdentity); + Assert.Null(model.GetTypeInfo(collections[0]).Type); - // Valid identity conversion matches the behavior for an ambiguous call - // with a switch expression argument: C.M(2 switch { _ => default }); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); Assert.True(conversion2.IsIdentity); @@ -24454,7 +25501,7 @@ public void MissingCtor_IEnumerable() using System.Collections; C x = [1]; // 1 - C.M([1]); // 2 + C.M([1]); class C : IEnumerable { @@ -24468,12 +25515,15 @@ public static void M(int[] i) { } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (3,7): error CS7036: There is no argument given that corresponds to the required parameter 's' of 'C.C(string)' + // (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_NoCorrespondingArgument, "[1]").WithArguments("s", "C.C(string)").WithLocation(3, 7), - // (4,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(C)' and 'C.M(int[])' - // C.M([1]); // 2 - Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(4, 3) + 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) ); var tree = comp.SyntaxTrees.First(); @@ -24481,13 +25531,15 @@ public static void M(int[] i) { } var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); var conversion1 = model.GetConversion(collections[0]); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); - Assert.True(conversion2.IsIdentity); - Assert.Null(model.GetTypeInfo(collections[1]).Type); + Assert.True(conversion2.IsCollectionExpression); + var typeInfo2 = model.GetTypeInfo(collections[1]); + Assert.Null(typeInfo2.Type); + Assert.Equal("System.Int32[]", typeInfo2.ConvertedType.ToTestDisplayString()); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24496,9 +25548,9 @@ public void MissingCtor_IEnumerable_Spread() string source = """ using System.Collections; - int[] values = [1]; + int[] values = new int[] { 1 }; C x = [..values]; // 1 - C.M([..values]); // 2 + C.M([..values]); class C : IEnumerable { @@ -24512,12 +25564,15 @@ public static void M(int[] i) { } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (4,7): error CS7036: There is no argument given that corresponds to the required parameter 's' of 'C.C(string)' + // (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_NoCorrespondingArgument, "[..values]").WithArguments("s", "C.C(string)").WithLocation(4, 7), - // (5,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(C)' and 'C.M(int[])' - // C.M([..values]); // 2 - Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(C)", "C.M(int[])").WithLocation(5, 3) + 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) ); var tree = comp.SyntaxTrees.First(); @@ -24525,13 +25580,15 @@ public static void M(int[] i) { } var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); var conversion1 = model.GetConversion(collections[0]); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); Assert.True(conversion2.IsCollectionExpression); - Assert.Null(model.GetTypeInfo(collections[1]).Type); + var typeInfo2 = model.GetTypeInfo(collections[1]); + Assert.Null(typeInfo2.Type); + Assert.Equal("System.Int32[]", typeInfo2.ConvertedType.ToTestDisplayString()); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24553,6 +25610,15 @@ public void Add(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 = [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) @@ -24589,6 +25655,15 @@ public static void M(int[] i) { } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( + // (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) @@ -24642,23 +25717,23 @@ public void MissingCtor_TypeParameter_GenericIEnumerable_NoElements() string source = """ using System.Collections; using System.Collections.Generic; - + interface IAdd { void Add(T t); } class C { - static T1 Create1() where T1 : IEnumerable => []; // 1 - static T2 Create2() where T2 : IEnumerable, new() => []; - static T3 Create3() where T3 : struct, IEnumerable => []; - static T4 Create4() where T4 : class, IEnumerable => []; // 2 + static T1 Create1() where T1 : IEnumerable, IAdd => []; // 1 + static T2 Create2() where T2 : IEnumerable, IAdd, new() => []; + static T3 Create3() where T3 : struct, IEnumerable, IAdd => []; + static T4 Create4() where T4 : class, IEnumerable, IAdd => []; // 2 } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (6,60): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint - // static T1 Create1() where T1 : IEnumerable => []; // 1 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T1").WithLocation(6, 60), - // (9,67): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint - // static T4 Create4() where T4 : class, IEnumerable => []; // 2 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T4").WithLocation(9, 67) + // (6,71): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint + // static T1 Create1() where T1 : IEnumerable, IAdd => []; // 1 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T1").WithLocation(6, 71), + // (9,78): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint + // static T4 Create4() where T4 : class, IEnumerable, IAdd => []; // 2 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T4").WithLocation(9, 78) ); var tree = comp.SyntaxTrees.First(); @@ -24666,8 +25741,8 @@ class C var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); var conversion1 = model.GetConversion(collections[0]); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); @@ -24686,8 +25761,8 @@ class C Assert.Equal("T3", typeInfo3.ConvertedType.ToTestDisplayString()); var conversion4 = model.GetConversion(collections[3]); - Assert.True(conversion4.IsValid); - Assert.True(conversion4.IsCollectionExpression); + Assert.False(conversion4.IsValid); + Assert.Equal(Conversion.NoConversion, conversion4); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24695,23 +25770,23 @@ public void MissingCtor_TypeParameter_IEnumerable() { string source = """ using System.Collections; - + interface IAdd { void Add(object o); } class C { - static T1 Create1() where T1 : IEnumerable => []; // 1 - static T2 Create2() where T2 : IEnumerable, new() => []; - static T3 Create3() where T3 : struct, IEnumerable => []; - static T4 Create4() where T4 : class, IEnumerable => []; // 2 + static T1 Create1() where T1 : IEnumerable, IAdd => []; // 1 + static T2 Create2() where T2 : IEnumerable, IAdd, new() => []; + static T3 Create3() where T3 : struct, IEnumerable, IAdd => []; + static T4 Create4() where T4 : class, IEnumerable, IAdd => []; // 2 } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (5,55): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint - // static T1 Create1() where T1 : IEnumerable => []; // 1 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T1").WithLocation(5, 55), - // (8,62): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint - // static T4 Create4() where T4 : class, IEnumerable => []; // 2 - Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T4").WithLocation(8, 62) + // (5,61): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint + // static T1 Create1() where T1 : IEnumerable, IAdd => []; // 1 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T1").WithLocation(5, 61), + // (8,68): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint + // static T4 Create4() where T4 : class, IEnumerable, IAdd => []; // 2 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[]").WithArguments("T4").WithLocation(8, 68) ); var tree = comp.SyntaxTrees.First(); @@ -24719,8 +25794,8 @@ class C var collections = tree.GetRoot().DescendantNodes().OfType().ToArray(); var conversion1 = model.GetConversion(collections[0]); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); var conversion2 = model.GetConversion(collections[1]); Assert.True(conversion2.IsValid); @@ -24739,8 +25814,8 @@ class C Assert.Equal("T3", typeInfo3.ConvertedType.ToTestDisplayString()); var conversion4 = model.GetConversion(collections[3]); - Assert.True(conversion4.IsValid); - Assert.True(conversion4.IsCollectionExpression); + Assert.False(conversion4.IsValid); + Assert.Equal(Conversion.NoConversion, conversion4); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24749,29 +25824,35 @@ public void MissingCtor_TypeParameter_IEnumerable_WithWrongGenericIEnumerable() string source = """ using System.Collections; using System.Collections.Generic; - + interface IAdd { void Add(T t); } class C { - static T1 Create1() where T1 : IEnumerable, IEnumerable => [1]; // 1 - static T2 Create2() where T2 : IEnumerable, IEnumerable, new() => [2]; // 2 - static T3 Create3() where T3 : struct, IEnumerable, IEnumerable => [3]; // 3 - static T4 Create4() where T4 : class, IEnumerable, IEnumerable => [4]; // 4 + static T1 Create1() where T1 : IEnumerable, IEnumerable, IAdd => [1]; // 1 + static T2 Create2() where T2 : IEnumerable, IEnumerable, IAdd, new() => [2]; // 2 + static T3 Create3() where T3 : struct, IEnumerable, IEnumerable, IAdd => [3]; // 3 + static T4 Create4() where T4 : class, IEnumerable, IEnumerable, IAdd => [4]; // 4 } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (6,77): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T1 Create1() where T1 : IEnumerable, IEnumerable => [1]; // 1 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "string").WithLocation(6, 77), - // (7,84): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T2 Create2() where T2 : IEnumerable, IEnumerable, new() => [2]; // 2 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "2").WithArguments("int", "string").WithLocation(7, 84), - // (8,85): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T3 Create3() where T3 : struct, IEnumerable, IEnumerable => [3]; // 3 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "3").WithArguments("int", "string").WithLocation(8, 85), - // (9,84): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T4 Create4() where T4 : class, IEnumerable, IEnumerable => [4]; // 4 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "4").WithArguments("int", "string").WithLocation(9, 84) + // (6,90): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint + // static T1 Create1() where T1 : IEnumerable, IEnumerable, IAdd => [1]; // 1 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[1]").WithArguments("T1").WithLocation(6, 90), + // (6,91): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T1 Create1() where T1 : IEnumerable, IEnumerable, IAdd => [1]; // 1 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "string").WithLocation(6, 91), + // (7,98): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T2 Create2() where T2 : IEnumerable, IEnumerable, IAdd, new() => [2]; // 2 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "2").WithArguments("int", "string").WithLocation(7, 98), + // (8,99): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T3 Create3() where T3 : struct, IEnumerable, IEnumerable, IAdd => [3]; // 3 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "3").WithArguments("int", "string").WithLocation(8, 99), + // (9,97): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint + // static T4 Create4() where T4 : class, IEnumerable, IEnumerable, IAdd => [4]; // 4 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[4]").WithArguments("T4").WithLocation(9, 97), + // (9,98): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T4 Create4() where T4 : class, IEnumerable, IEnumerable, IAdd => [4]; // 4 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "4").WithArguments("int", "string").WithLocation(9, 98) ); var tree = comp.SyntaxTrees.First(); @@ -24804,29 +25885,35 @@ public void MissingCtor_TypeParameter_WrongGenericIEnumerable() { string source = """ using System.Collections.Generic; - + interface IAdd { void Add(T t); } class C { - static T1 Create1() where T1 : IEnumerable => [1]; // 1 - static T2 Create2() where T2 : IEnumerable, new() => [2]; // 2 - static T3 Create3() where T3 : struct, IEnumerable => [3]; // 3 - static T4 Create4() where T4 : class, IEnumerable => [4]; // 4 + static T1 Create1() where T1 : IEnumerable, IAdd => [1]; // 1 + static T2 Create2() where T2 : IEnumerable, IAdd, new() => [2]; // 2 + static T3 Create3() where T3 : struct, IEnumerable, IAdd => [3]; // 3 + static T4 Create4() where T4 : class, IEnumerable, IAdd => [4]; // 4 } """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (5,64): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T1 Create1() where T1 : IEnumerable => [1]; // 1 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "string").WithLocation(5, 64), - // (6,71): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T2 Create2() where T2 : IEnumerable, new() => [2]; // 2 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "2").WithArguments("int", "string").WithLocation(6, 71), - // (7,72): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T3 Create3() where T3 : struct, IEnumerable => [3]; // 3 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "3").WithArguments("int", "string").WithLocation(7, 72), - // (8,71): error CS0029: Cannot implicitly convert type 'int' to 'string' - // static T4 Create4() where T4 : class, IEnumerable => [4]; // 4 - Diagnostic(ErrorCode.ERR_NoImplicitConv, "4").WithArguments("int", "string").WithLocation(8, 71) + // (5,77): error CS0304: Cannot create an instance of the variable type 'T1' because it does not have the new() constraint + // static T1 Create1() where T1 : IEnumerable, IAdd => [1]; // 1 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[1]").WithArguments("T1").WithLocation(5, 77), + // (5,78): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T1 Create1() where T1 : IEnumerable, IAdd => [1]; // 1 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "string").WithLocation(5, 78), + // (6,85): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T2 Create2() where T2 : IEnumerable, IAdd, new() => [2]; // 2 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "2").WithArguments("int", "string").WithLocation(6, 85), + // (7,86): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T3 Create3() where T3 : struct, IEnumerable, IAdd => [3]; // 3 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "3").WithArguments("int", "string").WithLocation(7, 86), + // (8,84): error CS0304: Cannot create an instance of the variable type 'T4' because it does not have the new() constraint + // static T4 Create4() where T4 : class, IEnumerable, IAdd => [4]; // 4 + Diagnostic(ErrorCode.ERR_NoNewTyvar, "[4]").WithArguments("T4").WithLocation(8, 84), + // (8,85): error CS0029: Cannot implicitly convert type 'int' to 'string' + // static T4 Create4() where T4 : class, IEnumerable, IAdd => [4]; // 4 + Diagnostic(ErrorCode.ERR_NoImplicitConv, "4").WithArguments("int", "string").WithLocation(8, 85) ); var tree = comp.SyntaxTrees.First(); @@ -24901,18 +25988,17 @@ static void Main() """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (17,11): error CS0144: Cannot create an instance of the abstract type or interface 'AbstractCollection' + // (17,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'AbstractCollection' // F([]); - Diagnostic(ErrorCode.ERR_NoNewAbstract, "[]").WithArguments("AbstractCollection").WithLocation(17, 11) - ); + Diagnostic(ErrorCode.ERR_BadArgType, "[]").WithArguments("1", "collection expressions", "AbstractCollection").WithLocation(17, 11)); var tree = comp.SyntaxTrees.First(); var model = comp.GetSemanticModel(tree); var collection = tree.GetRoot().DescendantNodes().OfType().Single(); Assert.Equal("[]", collection.ToString()); var conversion1 = model.GetConversion(collection); - Assert.True(conversion1.IsValid); - Assert.True(conversion1.IsCollectionExpression); + Assert.False(conversion1.IsValid); + Assert.Equal(Conversion.NoConversion, conversion1); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24944,9 +26030,9 @@ static void Main() """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (20,11): error CS0122: 'NoConstructorCollection.NoConstructorCollection()' is inaccessible due to its protection level + // (20,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'NoConstructorCollection' // F([]); - Diagnostic(ErrorCode.ERR_BadAccess, "[]").WithArguments("NoConstructorCollection.NoConstructorCollection()").WithLocation(20, 11) + Diagnostic(ErrorCode.ERR_BadArgType, "[]").WithArguments("1", "collection expressions", "NoConstructorCollection").WithLocation(20, 11) ); var tree = comp.SyntaxTrees.First(); @@ -24959,8 +26045,8 @@ static void Main() Assert.Equal("[]", collections[1].ToString()); var conversion2 = model.GetConversion(collections[1]); - Assert.True(conversion2.IsValid); - Assert.True(conversion2.IsCollectionExpression); + Assert.False(conversion2.IsValid); + Assert.Equal(Conversion.NoConversion, conversion2); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -24991,9 +26077,9 @@ static void Main() """; var comp = CreateCompilation(source).VerifyEmitDiagnostics( - // (19,11): error CS0122: 'NoConstructorCollection.NoConstructorCollection()' is inaccessible due to its protection level + // (19,11): error CS1503: Argument 1: cannot convert from 'collection expressions' to 'NoConstructorCollection' // F([1, 2, 3]); - Diagnostic(ErrorCode.ERR_BadAccess, "[1, 2, 3]").WithArguments("NoConstructorCollection.NoConstructorCollection()").WithLocation(19, 11) + Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2, 3]").WithArguments("1", "collection expressions", "NoConstructorCollection").WithLocation(19, 11) ); var tree = comp.SyntaxTrees.First(); @@ -25001,14 +26087,15 @@ static void Main() var collection = tree.GetRoot().DescendantNodes().OfType().Last(); Assert.Equal("[1, 2, 3]", collection.ToString()); var conversion = model.GetConversion(collection); - Assert.True(conversion.IsValid); - Assert.True(conversion.IsCollectionExpression); + Assert.False(conversion.IsValid); + Assert.Equal(Conversion.NoConversion, conversion); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] public void MissingCtor_OverloadResolution() { string source = """ + using System; using System.Collections; using System.Collections.Generic; @@ -25031,7 +26118,7 @@ class Program { static void F(AbstractCollection c) { } static void F(NoConstructorCollection c) { } - static void F(List c) { } + static void F(List c) { Console.WriteLine("List"); } static void Main() { @@ -25040,11 +26127,9 @@ static void Main() } """; - CreateCompilation(source).VerifyEmitDiagnostics( - // (27,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(AbstractCollection)' and 'Program.F(NoConstructorCollection)' - // F([]); - Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(AbstractCollection)", "Program.F(NoConstructorCollection)").WithLocation(27, 9) - ); + var comp = CreateCompilation(source, options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: "List"); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69521")] @@ -25231,16 +26316,16 @@ public void OverloadResolution_StringVsSpanInt() class C { public static void M(string s) => throw null; - public static void M(ReadOnlySpan s) => throw null; + public static void M(ReadOnlySpan s) + { + System.Console.Write($"{s[0]} {s[1]} {s[2]}"); + } } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics( - // (3,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M(string)' and 'C.M(ReadOnlySpan)' - // C.M(['a', 'b', 'c']); - Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M(string)", "C.M(System.ReadOnlySpan)").WithLocation(3, 3) - ); + comp.VerifyEmitDiagnostics(); + CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("97 98 99"), verify: Verification.FailsPEVerify); } [Fact] @@ -25272,8 +26357,19 @@ class MyCollection2 : IEnumerable where TAdd : TElemen """; var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); - CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("[1, 2, 3], [1, 2, 3],"), verify: Verification.FailsPEVerify); + 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)); } [Fact] @@ -25296,12 +26392,12 @@ class MyCollection2 : IEnumerable where TAdd : TElemen var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (4,33): error CS1950: The best overloaded Add method 'MyCollection2.Add(int)' for the collection initializer has some invalid arguments + // (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)'. // MyCollection2 y = [new object()]; - 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' + 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' // MyCollection2 y = [new object()]; - Diagnostic(ErrorCode.ERR_BadArgType, "new object()").WithArguments("1", "object", "int").WithLocation(4, 33) + Diagnostic(ErrorCode.ERR_BadArgType, "[new object()]").WithArguments("1", "object", "int").WithLocation(4, 32) ); } @@ -25309,7 +26405,7 @@ class MyCollection2 : IEnumerable where TAdd : TElemen public void GenericIEnumerable_DifferentConversionToAdd() { // For purpose of conversion, we rely on conversion from numeric literal to uint (from IEnumerable) - // But for purpose of execution, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) + // But for purpose of construction, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) string source = """ using System.Collections; using System.Collections.Generic; @@ -25327,15 +26423,20 @@ class MyCollection : IEnumerable """; var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); - comp.VerifyEmitDiagnostics(); - CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("[1, 2, 3],"), verify: Verification.FailsPEVerify); + 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)); } [Fact] public void GenericIEnumerable_NoConversionToAdd() { // For purpose of conversion, we rely on conversion from numeric literal to uint (from IEnumerable) - // But for purpose of execution, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) + // But for purpose of construction, we rely on conversion from numeric literal to sbyte (from Add(sbyte)) string source = """ using System.Collections; using System.Collections.Generic; @@ -25353,12 +26454,12 @@ class MyCollection : IEnumerable var comp = CreateCompilation(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // 0.cs(4,19): error CS1950: The best overloaded Add method 'MyCollection.Add(sbyte)' for the collection initializer has some invalid arguments + // 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 = [uint.MaxValue]; - 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' + 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' // MyCollection x = [uint.MaxValue]; - Diagnostic(ErrorCode.ERR_BadArgType, "uint.MaxValue").WithArguments("1", "uint", "sbyte").WithLocation(4, 19) + Diagnostic(ErrorCode.ERR_BadArgType, "[uint.MaxValue]").WithArguments("1", "uint", "sbyte").WithLocation(4, 18) ); } @@ -25509,6 +26610,9 @@ interface IColl : IEnumerable """; CreateCompilation(source, targetFramework: TargetFramework.Net80).VerifyEmitDiagnostics( + // (8,16): error CS0304: Cannot create an instance of the variable type 'T' because it does not have the new() constraint + // return ["hi", null]; + Diagnostic(ErrorCode.ERR_NoNewTyvar, @"[""hi"", null]").WithArguments("T").WithLocation(8, 16), // (8,17): error CS0029: Cannot implicitly convert type 'string' to 'int' // return ["hi", null]; Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""hi""").WithArguments("string", "int").WithLocation(8, 17), @@ -25550,7 +26654,38 @@ class Collection : IEnumerable, IEnumerable } [Fact] - public void NonGenericIEnumerable_TwoCompatibleInterfaces() + public void NonGenericIEnumerable_TwoCompatibleInterfaces_01() + { + string source = """ + using System.Collections; + using System.Collections.Generic; + + Collection c = [new C()]; + + interface I1 { } + interface I2 { } + + class C : I1, I2 { } + + class Collection : IEnumerable + { + IEnumerator IEnumerable.GetEnumerator() => null; + public void Add(I1 i) => throw null; + public void Add(I2 i) => throw null; + } + """; + + 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' + // Collection c = [new C()]; + Diagnostic(ErrorCode.ERR_BadArgType, "[new C()]").WithArguments("1", "object", "I1").WithLocation(4, 16)); + } + + [Fact] + public void NonGenericIEnumerable_TwoCompatibleInterfaces_02() { string source = """ using System.Collections; @@ -25566,6 +26701,7 @@ class C : I1, I2 { } class Collection : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => null; + public void Add(object o) => throw null; public void Add(I1 i) => throw null; public void Add(I2 i) => throw null; } @@ -26098,7 +27234,7 @@ namespace System.Collections.Immutable { struct ImmutableArray : IEnumerable { - public void Add(T t) { } + public void Add(object o) { } IEnumerator IEnumerable.GetEnumerator() => null; } } @@ -27510,14 +28646,14 @@ class CNotNull : IEnumerable { public CNotNull() { } IEnumerator IEnumerable.GetEnumerator() => throw null!; - public void Add(string s) { } + public void Add(object o) { } } class CNullable : IEnumerable { public CNullable() { } IEnumerator IEnumerable.GetEnumerator() => throw null!; - public void Add(string? s) { } + public void Add(object? o) { } } class COblivious : IEnumerable @@ -27525,7 +28661,7 @@ class COblivious : IEnumerable public COblivious() { } IEnumerator IEnumerable.GetEnumerator() => throw null!; #nullable disable - public void Add(string s) { } + public void Add(object o) { } } """; diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index 8f4efd59a9b76..473f6bead8e82 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -1399,7 +1399,7 @@ private DeclarationBodyMap IncludeLambdaBodyMaps( if (TryGetLambdaBodies(oldNode, out var oldLambdaBody1, out var oldLambdaBody2)) { lambdaBodyMaps ??= ArrayBuilder<(DeclarationBodyMap, SyntaxNode?)>.GetInstance(); - lazyActiveOrMatchedLambdas ??= []; + lazyActiveOrMatchedLambdas ??= new(); var newLambdaBody1 = oldLambdaBody1.TryGetPartnerLambdaBody(newNode); if (newLambdaBody1 != null)