From 77d31926ed0ea98de1add13d3e725a25674dd3a8 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 28 Jun 2023 17:59:50 -0700 Subject: [PATCH] Collection literals: address comments (#68793) --- .../Portable/Binder/Binder.ValueChecks.cs | 2 - .../Portable/Binder/Binder_Conversions.cs | 11 +- .../Semantics/Conversions/ConversionsBase.cs | 10 +- .../CSharp/Portable/Errors/ErrorCode.cs | 6 +- .../CSharp/Portable/Errors/MessageID.cs | 2 +- .../Portable/FlowAnalysis/NullableWalker.cs | 10 +- .../LocalRewriter_CollectionLiteral.cs | 10 +- .../Operations/CSharpOperationFactory.cs | 2 +- ...nTests_IArrayElementReferenceExpression.cs | 2 +- .../Semantics/CollectionLiteralTests.cs | 414 +++++++++++------- .../Parsing/CollectionLiteralParsingTests.cs | 9 +- 11 files changed, 292 insertions(+), 186 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index 856ff3d8acad0..1b74f95bbdfb3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -3960,7 +3960,6 @@ internal uint GetValEscape(BoundExpression expr, uint scopeOfTheContainingExpres return GetValEscape(switchExpr.SwitchArms.SelectAsArray(a => a.Value), scopeOfTheContainingExpression); case BoundKind.CollectionLiteralExpression: - // PROTOTYPE: Revisit if spans may be optimized to avoid heap allocation. return CallingMethodScope; default: @@ -4490,7 +4489,6 @@ internal bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint escapeF return true; case BoundKind.CollectionLiteralExpression: - // PROTOTYPE: Revisit if spans may be optimized to avoid heap allocation. return true; default: diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index aab5fed0951cc..49310842f8d82 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -575,7 +575,7 @@ private BoundCollectionLiteralExpression BindArrayOrSpanCollectionLiteral( if (elements.Any(e => e is BoundCollectionLiteralSpreadElement)) { // The array initializer includes at least one spread element, so we'll create an intermediate List instance. - // PROTOTYPE: Avoid the intermediate list if the compile-time type of the spread element includes a length. + // https://github.com/dotnet/roslyn/issues/68785: Avoid intermediate List if all spread elements have Length property. _ = GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_List_T__ToArray, diagnostics, syntax: syntax); var result = BindCollectionInitializerCollectionLiteral( node, @@ -642,7 +642,7 @@ private BoundCollectionLiteralExpression BindCollectionInitializerCollectionLite if (targetType is NamedTypeSymbol namedType) { var analyzedArguments = AnalyzedArguments.GetInstance(); - // PROTOTYPE: Should we use List(int capacity) constructor when the size is known? + // 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(); @@ -659,8 +659,6 @@ private BoundCollectionLiteralExpression BindCollectionInitializerCollectionLite } var implicitReceiver = new BoundObjectOrCollectionValuePlaceholder(syntax, isNewInstance: true, targetType) { WasCompilerGenerated = true }; - // PROTOTYPE: When generating a List, should we use the well-known - // member List.Add() rather than relying on lookup? var collectionInitializerAddMethodBinder = this.WithAdditionalFlags(BinderFlags.CollectionInitializerAddMethod); var builder = ArrayBuilder.GetInstance(node.Elements.Length); foreach (var element in node.Elements) @@ -668,9 +666,6 @@ private BoundCollectionLiteralExpression BindCollectionInitializerCollectionLite var result = element switch { BoundBadExpression => element, - // PROTOTYPE: Should spread elements support target type? - // string[] a = [..b ? [null] : []]; - // See CollectionLiteralTests.SpreadElement_05, _06. BoundCollectionLiteralSpreadElement spreadElement => BindCollectionInitializerSpreadElementAddMethod( (SpreadElementSyntax)spreadElement.Syntax, spreadElement, @@ -706,7 +701,7 @@ private BoundCollectionLiteralExpression BindListInterfaceCollectionLiteral( TypeSymbol elementType, BindingDiagnosticBag diagnostics) { - // PROTOTYPE: Improve perf. For instance, emit [] as Array.Empty() rather than a List. + // https://github.com/dotnet/roslyn/issues/68785: Emit [] as Array.Empty() rather than a List. var result = BindCollectionInitializerCollectionLiteral( node, CollectionLiteralTypeKind.ListInterface, diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 7bd3305b84936..1d73f6b58d3af 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -575,7 +575,6 @@ public Conversion ClassifyStandardConversion(BoundExpression sourceExpression, T return Conversion.NoConversion; } - // PROTOTYPE: Ensure collection literal conversions are not considered standard implicit conversions. private static bool IsStandardImplicitConversionFromExpression(ConversionKind kind) { if (IsStandardImplicitConversionFromType(kind)) @@ -1662,10 +1661,11 @@ static bool implementsIEnumerable(CSharpCompilation compilation, TypeSymbol targ } // This implementation differs from Binder.CollectionInitializerTypeImplementsIEnumerable(). - // That method checks for an implicit conversion from IEnumerable to the collection type, - // but that would allow: Nullable s = []; - // PROTOTYPE: Perhaps adjust the behavior of Binder.CollectionInitializerTypeImplementsIEnumerable() - // and use that method instead. + // That method checks for an implicit conversion from IEnumerable to the collection type, to + // match earlier implementation, even though it states that walking the implemented interfaces + // would be better. If we use CollectionInitializerTypeImplementsIEnumerable() here, we'd need + // to check for nullable to disallow: Nullable s = []; + // Instead, we just walk the implemented interfaces. var ienumerableType = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerable); return allInterfaces.Any(static (a, b) => areEqual(a, b), ienumerableType); } diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index ae886e9e7158e..7b1e978cb2af2 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2233,9 +2233,9 @@ internal enum ErrorCode ERR_InlineArrayBadIndex = 9172, ERR_NamedArgumentForInlineArray = 9173, - ERR_CollectionLiteralTargetTypeNotConstructible = 9500, // PROTOTYPE: Update error numbers. - ERR_ExpressionTreeContainsCollectionLiteral = 9501, - ERR_CollectionLiteralNoTargetType = 9503, + ERR_CollectionLiteralTargetTypeNotConstructible = 9174, + ERR_ExpressionTreeContainsCollectionLiteral = 9175, + ERR_CollectionLiteralNoTargetType = 9176, #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index ce8b62f4e4a2a..bb0db09864944 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -274,7 +274,7 @@ internal enum MessageID IDS_FeatureInstanceMemberInNameof = MessageBase + 12835, IDS_FeatureInlineArrays = MessageBase + 12836, - IDS_FeatureCollectionLiterals = MessageBase + 12900, // PROTOTYPE: Update message number. + IDS_FeatureCollectionLiterals = MessageBase + 12837, } // Message IDs may refer to strings that need to be localized. diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 47494760f3dd2..fdbc14aa2966f 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -3473,12 +3473,12 @@ protected override void VisitStatement(BoundStatement statement) public override BoundNode? VisitCollectionLiteralExpression(BoundCollectionLiteralExpression node) { - // PROTOTYPE: Do we need to call inferInitialObjectState() to set the initial state of the instance? + // https://github.com/dotnet/roslyn/issues/68786: Use inferInitialObjectState() to set the initial + // state of the instance: see the call to InheritNullableStateOfTrackableStruct() in particular. int containerSlot = GetOrCreatePlaceholderSlot(node); - bool delayCompletionForType = false; // PROTOTYPE: Should be true if the collection literal is target typed. + bool delayCompletionForType = false; // https://github.com/dotnet/roslyn/issues/68786: Should be true if the collection literal is target typed. - // PROTOTYPE: Test nullability of elements when the collection literal is target typed - // and the inferred target type has distinct element type nullability. + // https://github.com/dotnet/roslyn/issues/68786: Set nullability of elements from the inferred target type nullability. foreach (var element in node.Elements) { switch (element) @@ -3488,7 +3488,7 @@ protected override void VisitStatement(BoundStatement statement) var completion = VisitCollectionElementInitializer(initializer, collectionType, delayCompletionForType); if (completion is { }) { - // PROTOTYPE: Complete the analysis later. + // https://github.com/dotnet/roslyn/issues/68786: Complete the analysis later. completion(containerSlot, collectionType); } break; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionLiteral.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionLiteral.cs index 01172c81e1c19..073f4b60b73d9 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionLiteral.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionLiteral.cs @@ -61,17 +61,17 @@ private BoundExpression VisitArrayOrSpanCollectionLiteralExpression(BoundCollect if (elements.Any(i => i is BoundCollectionLiteralSpreadElement)) { // The array initializer includes at least one spread element, so we'll create an intermediate List instance. - // PROTOTYPE: Avoid the intermediate list if the compile-time type of the spread element includes a length. - // PROTOTYPE: Use Enumerable.TryGetNonEnumeratedCount() at runtime for other cases. + // https://github.com/dotnet/roslyn/issues/68785: Avoid intermediate List if all spread elements have Length property. + // https://github.com/dotnet/roslyn/issues/68785: Emit Enumerable.TryGetNonEnumeratedCount() and avoid intermediate List at runtime. var listType = _compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_List_T).Construct(elementType); var listToArray = ((MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_List_T__ToArray)!).AsMember(listType); var list = VisitCollectionInitializerCollectionLiteralExpression(node); - array = _factory.Call(list, listToArray); // PROTOTYPE: Improve perf. For instance, avoid copying to a new array. + array = _factory.Call(list, listToArray); } else { int arrayLength = elements.Length; - // PROTOTYPE: Should [] be emitted as Array.Empty()? + // https://github.com/dotnet/roslyn/issues/68785: Emit [] as Array.Empty() rather than a List. var initialization = (arrayLength == 0) ? null : new BoundArrayInitialization( @@ -149,7 +149,7 @@ private BoundExpression VisitListInterfaceCollectionLiteralExpression(BoundColle Debug.Assert(!_inExpressionLambda); Debug.Assert(node.Type is { }); - // PROTOTYPE: Improve perf. For instance, emit [] as Array.Empty() rather than a List. + // https://github.com/dotnet/roslyn/issues/68785: Emit [] as Array.Empty() rather than a List. var list = VisitCollectionInitializerCollectionLiteralExpression(node); return _factory.Convert(node.Type, list); } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index dbc0213114d5b..a09e5851da179 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1247,7 +1247,7 @@ ImmutableArray createChildren(ImmutableArray elemen { var element = expression switch { - BoundCollectionElementInitializer initializer => initializer.Arguments.FirstOrDefault(), + BoundCollectionElementInitializer initializer => initializer.Arguments.First(), _ => expression, }; return Create(element); diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArrayElementReferenceExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArrayElementReferenceExpression.cs index 2673938ef639c..283925bba23e6 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArrayElementReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArrayElementReferenceExpression.cs @@ -525,7 +525,7 @@ public void F() "; var expectedDiagnostics = new DiagnosticDescription[] { - // (6,27): error CS9503: There is no target type for the collection literal. + // (6,27): error CS9176: There is no target type for the collection literal. // var a = /**/[0]/**/; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[0]").WithLocation(6, 27) }; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/CollectionLiteralTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/CollectionLiteralTests.cs index dede6bfdcdb34..5cbc7e5dd58eb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/CollectionLiteralTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/CollectionLiteralTests.cs @@ -159,13 +159,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("object").WithLocation(5, 20), - // (6,21): error CS9500: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. + // (6,21): error CS9174: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. // dynamic y = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("dynamic").WithLocation(6, 21), - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var z = []; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(7, 17)); @@ -194,13 +194,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object x = [1]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1]").WithArguments("object").WithLocation(5, 20), - // (6,21): error CS9500: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. + // (6,21): error CS9174: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. // dynamic y = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("dynamic").WithLocation(6, 21), - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var z = [3]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[3]").WithLocation(7, 17)); @@ -229,13 +229,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object x = [1, ""]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, @"[1, """"]").WithArguments("object").WithLocation(5, 20), - // (6,21): error CS9500: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. + // (6,21): error CS9174: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. // dynamic y = [2, ""]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, @"[2, """"]").WithArguments("dynamic").WithLocation(6, 21), - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var z = [3, ""]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, @"[3, """"]").WithLocation(7, 17)); } @@ -257,13 +257,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object x = [null]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[null]").WithArguments("object").WithLocation(5, 20), - // (6,21): error CS9500: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. + // (6,21): error CS9174: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. // dynamic y = [null]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[null]").WithArguments("dynamic").WithLocation(6, 21), - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var z = [null]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[null]").WithLocation(7, 17)); } @@ -285,13 +285,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,17): error CS9503: There is no target type for the collection literal. + // (5,17): error CS9176: There is no target type for the collection literal. // var x = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[1, 2, null]").WithLocation(5, 17), - // (6,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (6,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object y = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2, null]").WithArguments("object").WithLocation(6, 20), - // (7,21): error CS9500: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. + // (7,21): error CS9174: Cannot initialize type 'dynamic' with a collection literal because the type is not constructible. // dynamic z = [1, 2, null]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2, null]").WithArguments("dynamic").WithLocation(7, 21)); } @@ -310,7 +310,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,23): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,23): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object[] x = [[]]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("object").WithLocation(5, 23)); } @@ -329,7 +329,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,23): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (5,23): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object[] y = [[2]]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("object").WithLocation(5, 23)); } @@ -348,7 +348,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,17): error CS9503: There is no target type for the collection literal. + // (5,17): error CS9176: There is no target type for the collection literal. // var z = [[3]]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[[3]]").WithLocation(5, 17)); } @@ -442,13 +442,13 @@ static void Main() """; var comp = CreateCompilation(new[] { source, s_collectionExtensions }); comp.VerifyEmitDiagnostics( - // 0.cs(6,25): error CS9500: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. + // 0.cs(6,25): error CS9174: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. // IEnumerable a = [1]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1]").WithArguments("System.Collections.IEnumerable").WithLocation(6, 25), - // 0.cs(7,25): error CS9500: Cannot initialize type 'ICollection' with a collection literal because the type is not constructible. + // 0.cs(7,25): error CS9174: Cannot initialize type 'ICollection' with a collection literal because the type is not constructible. // ICollection b = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("System.Collections.ICollection").WithLocation(7, 25), - // 0.cs(8,19): error CS9500: Cannot initialize type 'IList' with a collection literal because the type is not constructible. + // 0.cs(8,19): error CS9174: Cannot initialize type 'IList' with a collection literal because the type is not constructible. // IList c = [3]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[3]").WithArguments("System.Collections.IList").WithLocation(8, 19)); } @@ -523,10 +523,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,17): error CS9503: There is no target type for the collection literal. + // (5,17): error CS9176: There is no target type for the collection literal. // var x = [null, 1]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[null, 1]").WithLocation(5, 17), - // (6,20): error CS9500: Cannot initialize type 'object' with a collection literal because the type is not constructible. + // (6,20): error CS9174: Cannot initialize type 'object' with a collection literal because the type is not constructible. // object y = [null, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[null, 2]").WithArguments("object").WithLocation(6, 20)); } @@ -556,16 +556,16 @@ static void F2(int i) var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (12,18): error CS9503: There is no target type for the collection literal. + // (12,18): error CS9176: There is no target type for the collection literal. // var x2 = [(null, default)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[(null, default)]").WithLocation(12, 18), - // (13,18): error CS9503: There is no target type for the collection literal. + // (13,18): error CS9176: There is no target type for the collection literal. // var y2 = [i switch { _ => default }]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[i switch { _ => default }]").WithLocation(13, 18), // (13,21): error CS8506: No best type was found for the switch expression. // var y2 = [i switch { _ => default }]; Diagnostic(ErrorCode.ERR_SwitchExpressionNoBestType, "switch").WithLocation(13, 21), - // (14,18): error CS9503: There is no target type for the collection literal. + // (14,18): error CS9176: There is no target type for the collection literal. // var z2 = [i == 0 ? null : default]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[i == 0 ? null : default]").WithLocation(14, 18), // (14,19): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between '' and 'default' @@ -1168,7 +1168,6 @@ static void Main() } } """; - // PROTOTYPE: Should compile and run successfully: expectedOutput: "[1, 2, 3], " var comp = CreateCompilation(new[] { source, s_collectionExtensions }); comp.VerifyEmitDiagnostics( // 0.cs(9,29): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'collection literals' and 'collection literals' @@ -1195,7 +1194,7 @@ static void Main() """; var comp = CreateCompilation(new[] { source, s_collectionExtensions }); comp.VerifyEmitDiagnostics( - // 0.cs(9,17): error CS9503: There is no target type for the collection literal. + // 0.cs(9,17): error CS9176: There is no target type for the collection literal. // var a = [1, 2, 3].AsArray(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[1, 2, 3]").WithLocation(9, 17)); } @@ -1236,7 +1235,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (27,17): error CS9503: There is no target type for the collection literal. + // (27,17): error CS9176: There is no target type for the collection literal. // var b = [4].AsCollection(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[4]").WithLocation(27, 17)); } @@ -1269,7 +1268,7 @@ static void Main() // (15,13): error CS0411: The type arguments for method 'Program.AsCollection(S)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // _ = AsCollection([1, 2, 3]); Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "AsCollection").WithArguments("Program.AsCollection(S)").WithLocation(15, 13), - // (16,13): error CS9503: There is no target type for the collection literal. + // (16,13): error CS9176: There is no target type for the collection literal. // _ = [4].AsCollection(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[4]").WithLocation(16, 13)); } @@ -1320,7 +1319,6 @@ static void Main() CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Int32[]) [1, 2, 3], "); } - // PROTOTYPE: Test other variance cases. [Fact] public void TypeInference_12() { @@ -1340,10 +1338,8 @@ static void Main() CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Object[]) [1], (System.Object[]) [3], "); } - // PROTOTYPE: Test other variance cases. And these are just for array inferences. - // What about constructed collection type inferences? [Fact] - public void TypeInference_13() + public void TypeInference_13A() { string source = """ class Program @@ -1361,6 +1357,26 @@ static void Main() CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Int64[]) [1], (System.Int64[]) [3], "); } + [Fact] + public void TypeInference_13B() + { + string source = """ + using System.Collections.Generic; + class Program + { + static HashSet F(HashSet x, HashSet y) => x; + static void Main() + { + var x = F([1], [(long)2]); + x.Report(includeType: true); + var y = F([(long)3], [4]); + y.Report(includeType: true); + } + } + """; + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Collections.Generic.HashSet) [1], (System.Collections.Generic.HashSet) [3], "); + } + [Fact] public void TypeInference_14() { @@ -1931,6 +1947,114 @@ static void Main() expectedOutput: "(System.ValueTuple[]) [(1, 2)], (System.ValueTuple[]) [(0, 0), (3, 4)], "); } + [Fact] + public void TypeInference_38() + { + string source = """ + class Program + { + static T[] F1(T[] x, T y) => x; + static T[] F2(T[] x, ref T y) => x; + static T[] F3(T[] x, in T y) => x; + static T[] F4(T[] x, out T y) { y = default; return x; } + static void Main() + { + object y = null; + var x1 = F1([1], y); + var x2 = F2([2], ref y); + var x3A = F3([3], y); + var x3B = F3([3], in y); + var x4 = F4([4], out y); + x1.Report(true); + x2.Report(true); + x3A.Report(true); + x3B.Report(true); + x4.Report(true); + } + } + """; + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Object[]) [1], (System.Object[]) [2], (System.Object[]) [3], (System.Object[]) [3], (System.Object[]) [4], "); + } + + [Fact] + public void TypeInference_39A() + { + string source = """ + class Program + { + static T[] F1(T[] x, T y) => x; + static T[] F3(T[] x, in T y) => x; + static void Main() + { + byte y = 0; + var x1 = F1([1], y); + var x3A = F3([3], y); + x1.Report(true); + x3A.Report(true); + } + } + """; + CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "(System.Int32[]) [1], (System.Int32[]) [3], "); + } + + [Fact] + public void TypeInference_39B() + { + string source = """ + class Program + { + static T[] F2(T[] x, ref T y) => x; + static T[] F3(T[] x, in T y) => x; + static T[] F4(T[] x, out T y) { y = default; return x; } + static void Main() + { + byte y = 0; + var x2 = F2([2], ref y); + var x3B = F3([3], in y); + var x4 = F4([4], out y); + } + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (9,18): error CS0411: The type arguments for method 'Program.F2(T[], ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // var x2 = F2([2], ref y); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F2").WithArguments("Program.F2(T[], ref T)").WithLocation(9, 18), + // (10,19): error CS0411: The type arguments for method 'Program.F3(T[], in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // var x3B = F3([3], in y); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F3").WithArguments("Program.F3(T[], in T)").WithLocation(10, 19), + // (11,18): error CS0411: The type arguments for method 'Program.F4(T[], out T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // var x4 = F4([4], out y); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F4").WithArguments("Program.F4(T[], out T)").WithLocation(11, 18)); + } + + [Fact] + public void TypeInference_40() + { + string source = """ + using System; + class Program + { + static Func F(Func arg) => arg; + static void Main(string[] args) + { + var x = F(() => [1, 2, 3]); + x.Report(includeType: true); + var y = F(() => { if (args.Length == 0) return []; return [1, 2, 3]; }); + y.Report(includeType: true); + } + } + """; + var comp = CreateCompilation(new[] { source, s_collectionExtensions }); + comp.VerifyEmitDiagnostics( + // 0.cs(7,17): error CS0411: The type arguments for method 'Program.F(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // var x = F(() => [1, 2, 3]); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("Program.F(System.Func)").WithLocation(7, 17), + // 0.cs(9,17): error CS0411: The type arguments for method 'Program.F(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // var y = F(() => { if (args.Length == 0) return []; return [1, 2, 3]; }); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("Program.F(System.Func)").WithLocation(9, 17)); + } + [Fact] public void MemberAccess_01() { @@ -1947,13 +2071,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,9): error CS9503: There is no target type for the collection literal. + // (5,9): error CS9176: There is no target type for the collection literal. // [].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(5, 9), - // (6,9): error CS9503: There is no target type for the collection literal. + // (6,9): error CS9176: There is no target type for the collection literal. // []?.GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(6, 9), - // (7,9): error CS9503: There is no target type for the collection literal. + // (7,9): error CS9176: There is no target type for the collection literal. // [][0].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(7, 9)); } @@ -1974,13 +2098,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,9): error CS9503: There is no target type for the collection literal. + // (5,9): error CS9176: There is no target type for the collection literal. // [1].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[1]").WithLocation(5, 9), - // (6,9): error CS9503: There is no target type for the collection literal. + // (6,9): error CS9176: There is no target type for the collection literal. // [2]?.GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[2]").WithLocation(6, 9), - // (7,9): error CS9503: There is no target type for the collection literal. + // (7,9): error CS9176: There is no target type for the collection literal. // [3][0].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[3]").WithLocation(7, 9)); } @@ -2001,13 +2125,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,13): error CS9503: There is no target type for the collection literal. + // (5,13): error CS9176: There is no target type for the collection literal. // _ = [].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(5, 13), - // (6,13): error CS9503: There is no target type for the collection literal. + // (6,13): error CS9176: There is no target type for the collection literal. // _ = []?.GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(6, 13), - // (7,13): error CS9503: There is no target type for the collection literal. + // (7,13): error CS9176: There is no target type for the collection literal. // _ = [][0].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(7, 13)); } @@ -2028,13 +2152,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,13): error CS9503: There is no target type for the collection literal. + // (5,13): error CS9176: There is no target type for the collection literal. // _ = [1].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[1]").WithLocation(5, 13), - // (6,13): error CS9503: There is no target type for the collection literal. + // (6,13): error CS9176: There is no target type for the collection literal. // _ = [2]?.GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[2]").WithLocation(6, 13), - // (7,13): error CS9503: There is no target type for the collection literal. + // (7,13): error CS9176: There is no target type for the collection literal. // _ = [3][0].GetHashCode(); Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[3]").WithLocation(7, 13)); } @@ -2082,10 +2206,6 @@ static void Main() } } """; - // PROTOTYPE: Confirm we should generate ListBase instances for both x and y. - // (We should use the target type ListBase in each case because it implements IEnumerable, rather than - // using the natural type List, even though ListBase.Add(string) has the wrong parameter type.) - // Add similar test where ListBase has no Add method. We should still use ListBase for x and y. 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. @@ -2152,13 +2272,13 @@ 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,16): error CS9500: Cannot initialize type 'IA' with a collection literal because the type is not constructible. + // 1.cs(7,16): error CS9174: Cannot initialize type 'IA' with a collection literal because the type is not constructible. // IA a = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("System.Collections.Generic.IA").WithLocation(7, 16), - // 1.cs(9,24): error CS9500: Cannot initialize type 'IC' with a collection literal because the type is not constructible. + // 1.cs(9,24): error CS9174: Cannot initialize type 'IC' with a collection literal because the type is not constructible. // IC c = [4]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[4]").WithArguments("System.Collections.Generic.IC").WithLocation(9, 24), - // 1.cs(10,32): error CS9500: Cannot initialize type 'ID' with a collection literal because the type is not constructible. + // 1.cs(10,32): error CS9174: Cannot initialize type 'ID' with a collection literal because the type is not constructible. // ID d = [5]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[5]").WithArguments("System.Collections.Generic.ID").WithLocation(10, 32)); } @@ -2210,7 +2330,7 @@ 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(8,29): error CS9500: Cannot initialize type 'IEquatable' with a collection literal because the type is not constructible. + // 1.cs(8,29): error CS9174: Cannot initialize type 'IEquatable' with a collection literal because the type is not constructible. // IEquatable e = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("System.IEquatable").WithLocation(8, 29)); } @@ -2254,10 +2374,10 @@ 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 CS9500: Cannot initialize type 'List' with a collection literal because the type is not constructible. + // 1.cs(7,23): error CS9174: Cannot initialize type 'List' with a collection literal because the type is not constructible. // List l = [1]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1]").WithArguments("System.Collections.Generic.List").WithLocation(7, 23), - // 1.cs(8,30): error CS9500: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. + // 1.cs(8,30): error CS9174: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. // IEnumerable e = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("System.Collections.Generic.IEnumerable").WithLocation(8, 30)); } @@ -2282,19 +2402,19 @@ static void Main() var comp = CreateCompilation(source); comp.MakeTypeMissing(WellKnownType.System_Collections_Generic_List_T); comp.VerifyEmitDiagnostics( - // (6,30): error CS9500: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. + // (6,30): error CS9174: Cannot initialize type 'IEnumerable' with a collection literal because the type is not constructible. // IEnumerable a = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("System.Collections.Generic.IEnumerable").WithLocation(6, 30), - // (7,30): error CS9500: Cannot initialize type 'ICollection' with a collection literal because the type is not constructible. + // (7,30): error CS9174: Cannot initialize type 'ICollection' with a collection literal because the type is not constructible. // ICollection b = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("System.Collections.Generic.ICollection").WithLocation(7, 30), - // (8,24): error CS9500: Cannot initialize type 'IList' with a collection literal because the type is not constructible. + // (8,24): error CS9174: Cannot initialize type 'IList' with a collection literal because the type is not constructible. // IList c = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("System.Collections.Generic.IList").WithLocation(8, 24), - // (9,38): error CS9500: Cannot initialize type 'IReadOnlyCollection' with a collection literal because the type is not constructible. + // (9,38): error CS9174: Cannot initialize type 'IReadOnlyCollection' with a collection literal because the type is not constructible. // IReadOnlyCollection d = [3]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[3]").WithArguments("System.Collections.Generic.IReadOnlyCollection").WithLocation(9, 38), - // (10,32): error CS9500: Cannot initialize type 'IReadOnlyList' with a collection literal because the type is not constructible. + // (10,32): error CS9174: Cannot initialize type 'IReadOnlyList' with a collection literal because the type is not constructible. // IReadOnlyList e = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("System.Collections.Generic.IReadOnlyList").WithLocation(10, 32)); } @@ -2503,10 +2623,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,23): error CS9500: Cannot initialize type 'object[*,*]' with a collection literal because the type is not constructible. + // (5,23): error CS9174: Cannot initialize type 'object[*,*]' with a collection literal because the type is not constructible. // object[,] x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("object[*,*]").WithLocation(5, 23), - // (6,20): error CS9500: Cannot initialize type 'int[*,*]' with a collection literal because the type is not constructible. + // (6,20): error CS9174: Cannot initialize type 'int[*,*]' with a collection literal because the type is not constructible. // int[,] y = [null, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[null, 2]").WithArguments("int[*,*]").WithLocation(6, 20)); } @@ -2525,7 +2645,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,20): error CS9500: Cannot initialize type 'int[*,*]' with a collection literal because the type is not constructible. + // (5,20): error CS9174: Cannot initialize type 'int[*,*]' with a collection literal because the type is not constructible. // int[,] z = [[1, 2], [3, 4]]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[[1, 2], [3, 4]]").WithArguments("int[*,*]").WithLocation(5, 20)); } @@ -2789,10 +2909,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (26,13): error CS9500: Cannot initialize type 'I' with a collection literal because the type is not constructible. + // (26,13): error CS9174: Cannot initialize type 'I' with a collection literal because the type is not constructible. // i = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("I").WithLocation(26, 13), - // (27,13): error CS9500: Cannot initialize type 'I' with a collection literal because the type is not constructible. + // (27,13): error CS9174: Cannot initialize type 'I' with a collection literal because the type is not constructible. // i = [3, 4]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[3, 4]").WithArguments("I").WithLocation(27, 13)); } @@ -2814,10 +2934,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,13): error CS9500: Cannot initialize type 'E' with a collection literal because the type is not constructible. + // (7,13): error CS9174: Cannot initialize type 'E' with a collection literal because the type is not constructible. // e = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("E").WithLocation(7, 13), - // (8,13): error CS9500: Cannot initialize type 'E' with a collection literal because the type is not constructible. + // (8,13): error CS9174: Cannot initialize type 'E' with a collection literal because the type is not constructible. // e = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("E").WithLocation(8, 13)); } @@ -2865,10 +2985,10 @@ 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,13): error CS9500: Cannot initialize type 'E' with a collection literal because the type is not constructible. + // 1.cs(7,13): error CS9174: Cannot initialize type 'E' with a collection literal because the type is not constructible. // e = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("E").WithLocation(7, 13), - // 1.cs(8,13): error CS9500: Cannot initialize type 'E' with a collection literal because the type is not constructible. + // 1.cs(8,13): error CS9174: Cannot initialize type 'E' with a collection literal because the type is not constructible. // e = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("E").WithLocation(8, 13)); } @@ -2890,10 +3010,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (7,13): error CS9500: Cannot initialize type 'D' with a collection literal because the type is not constructible. + // (7,13): error CS9174: Cannot initialize type 'D' with a collection literal because the type is not constructible. // d = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("D").WithLocation(7, 13), - // (8,13): error CS9500: Cannot initialize type 'D' with a collection literal because the type is not constructible. + // (8,13): error CS9174: Cannot initialize type 'D' with a collection literal because the type is not constructible. // d = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("D").WithLocation(8, 13)); } @@ -2943,10 +3063,10 @@ 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,13): error CS9500: Cannot initialize type 'D' with a collection literal because the type is not constructible. + // 1.cs(7,13): error CS9174: Cannot initialize type 'D' with a collection literal because the type is not constructible. // d = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("D").WithLocation(7, 13), - // 1.cs(8,13): error CS9500: Cannot initialize type 'D' with a collection literal because the type is not constructible. + // 1.cs(8,13): error CS9174: Cannot initialize type 'D' with a collection literal because the type is not constructible. // d = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("D").WithLocation(8, 13)); } @@ -2967,13 +3087,13 @@ unsafe static void Main() """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe); comp.VerifyEmitDiagnostics( - // (5,18): error CS9500: Cannot initialize type 'int*' with a collection literal because the type is not constructible. + // (5,18): error CS9174: Cannot initialize type 'int*' with a collection literal because the type is not constructible. // int* x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("int*").WithLocation(5, 18), - // (6,18): error CS9500: Cannot initialize type 'int*' with a collection literal because the type is not constructible. + // (6,18): error CS9174: Cannot initialize type 'int*' with a collection literal because the type is not constructible. // int* y = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("int*").WithLocation(6, 18), - // (7,17): error CS9500: Cannot initialize type 'int*' with a collection literal because the type is not constructible. + // (7,17): error CS9174: Cannot initialize type 'int*' with a collection literal because the type is not constructible. // var z = (int*)[3]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(int*)[3]").WithArguments("int*").WithLocation(7, 17)); } @@ -2994,13 +3114,13 @@ unsafe static void Main() """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe); comp.VerifyEmitDiagnostics( - // (5,29): error CS9500: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. + // (5,29): error CS9174: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. // delegate* x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("delegate*").WithLocation(5, 29), - // (6,29): error CS9500: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. + // (6,29): error CS9174: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. // delegate* y = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("delegate*").WithLocation(6, 29), - // (7,17): error CS9500: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. + // (7,17): error CS9174: Cannot initialize type 'delegate*' with a collection literal because the type is not constructible. // var z = (delegate*)[3]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(delegate*)[3]").WithArguments("delegate*").WithLocation(7, 17)); } @@ -3022,10 +3142,10 @@ unsafe static void Main() """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe); comp.VerifyEmitDiagnostics( - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var x = [p]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[p]").WithLocation(7, 17), - // (8,17): error CS9503: There is no target type for the collection literal. + // (8,17): error CS9176: There is no target type for the collection literal. // var y = [d]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[d]").WithLocation(8, 17)); } @@ -3169,13 +3289,13 @@ struct S { } """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (2,5): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (2,5): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S").WithLocation(2, 5), - // (3,5): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (3,5): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("S").WithLocation(3, 5), - // (4,5): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (4,5): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = [default]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[default]").WithArguments("S").WithLocation(4, 5), // (5,6): error CS0103: The name 'Unknown' does not exist in the current context @@ -3942,7 +4062,7 @@ class Program """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (16,57): error CS9500: Cannot initialize type 'T?' with a collection literal because the type is not constructible. + // (16,57): error CS9174: Cannot initialize type 'T?' with a collection literal because the type is not constructible. // static T? Create2() where T : struct, I => []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("T?").WithLocation(16, 57)); } @@ -4016,10 +4136,10 @@ static void Main() var comp = CreateCompilation(source); comp.MakeTypeMissing(SpecialType.System_Collections_IEnumerable); comp.VerifyEmitDiagnostics( - // (8,15): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (8,15): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // S s = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S").WithLocation(8, 15), - // (9,20): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (9,20): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // object o = (S)([1, 2]); Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(S)([1, 2])").WithArguments("S").WithLocation(9, 20)); } @@ -4151,7 +4271,7 @@ static void Main() [ConditionalTheory(typeof(CoreClrOnly))] [CombinatorialData] public void SpreadElement_01( - [CombinatorialValues("IEnumerable", "IEnumerable", "int[]", "List", "Span", "ReadOnlySpan")] string spreadType, + [CombinatorialValues("IEnumerable", "int[]", "List", "Span", "ReadOnlySpan")] string spreadType, [CombinatorialValues("IEnumerable", "int[]", "List", "Span", "ReadOnlySpan")] string collectionType) { string source = $$""" @@ -4168,9 +4288,6 @@ static void Main() } """; - // PROTOTYPE: Should IEnumerable contribute object or no type to the best common type? - if (spreadType == "IEnumerable") return; - var verifier = CompileAndVerify( new[] { source, s_collectionExtensionsWithSpan }, options: TestOptions.ReleaseExe, @@ -4261,7 +4378,7 @@ .locals init (System.Collections.Generic.List V_0, } """, ("int[]", "int[]") => - // PROTOTYPE: Shouldn't require an intermediate List since the compiler can use e.Length directly. + // https://github.com/dotnet/roslyn/issues/68785: Avoid intermediate List if all spread elements have Length property. """ { // Code size 40 (0x28) @@ -4299,7 +4416,7 @@ .locals init (System.Collections.Generic.List V_0, } """, ("ReadOnlySpan", "ReadOnlySpan") => - // PROTOTYPE: Shouldn't require an intermediate List since the compiler can use e.Length directly. + // https://github.com/dotnet/roslyn/issues/68785: Avoid intermediate List if all spread elements have Length property. """ { // Code size 53 (0x35) @@ -4559,7 +4676,7 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (5,26): error CS9503: There is no target type for the collection literal. + // (5,26): error CS9176: There is no target type for the collection literal. // var a = [1, 2, ..[]]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(5, 26)); } @@ -4579,12 +4696,11 @@ static void Main() } """; var comp = CreateCompilation(source); - // PROTOTYPE: Should spread elements support target type? (Should we infer IEnumerable?) comp.VerifyEmitDiagnostics( - // (6,21): error CS9503: There is no target type for the collection literal. + // (6,21): error CS9176: There is no target type for the collection literal. // a = [..a, ..[]]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[]").WithLocation(6, 21), - // (7,16): error CS9503: There is no target type for the collection literal. + // (7,16): error CS9176: There is no target type for the collection literal. // a = [..[default]]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[default]").WithLocation(7, 16)); } @@ -4601,7 +4717,6 @@ static string[] Append(string a, string b, bool c) } } """; - // PROTOTYPE: Should spread elements support target type? (Should we infer IEnumerable?) var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( // (5,26): error CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between 'collection literals' and 'collection literals' @@ -4878,6 +4993,33 @@ static void Main() CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[1, 2, 3, 4], "); } + [Fact] + public void SpreadElement_11() + { + string source = """ + using System.Collections; + class Program + { + static void Main() + { + F([1, 2, 3]); + } + static int[] F(IEnumerable s) => [..s]; + } + """; + var comp = CreateCompilation(source); + comp.VerifyEmitDiagnostics( + // (6,11): error CS1503: Argument 1: cannot convert from 'collection literals' to 'System.Collections.IEnumerable' + // F([1, 2, 3]); + Diagnostic(ErrorCode.ERR_BadArgType, "[1, 2, 3]").WithArguments("1", "collection literals", "System.Collections.IEnumerable").WithLocation(6, 11), + // (8,39): error CS1950: The best overloaded Add method 'List.Add(int)' for the collection initializer has some invalid arguments + // static int[] F(IEnumerable s) => [..s]; + Diagnostic(ErrorCode.ERR_BadArgTypesForCollectionAdd, "..s").WithArguments("System.Collections.Generic.List.Add(int)").WithLocation(8, 39), + // (8,39): error CS1503: Argument 1: cannot convert from 'object' to 'int' + // static int[] F(IEnumerable s) => [..s]; + Diagnostic(ErrorCode.ERR_BadArgType, "..s").WithArguments("1", "object", "int").WithLocation(8, 39)); + } + [Theory] [InlineData("object[]")] [InlineData("List")] @@ -4991,7 +5133,7 @@ static void Main() var comp = CreateCompilation(source); comp.MakeTypeMissing(WellKnownType.System_Collections_Generic_List_T); - // PROTOTYPE: Should report missing List, and only report for [..e] case only, not [..a]. + // https://github.com/dotnet/roslyn/issues/68785: Should not report missing List for [..a]. comp.VerifyEmitDiagnostics( // (9,13): error CS0656: Missing compiler required member 'System.Collections.Generic.List`1.ToArray' // b = [..a]; @@ -5008,7 +5150,7 @@ static void Main() comp = CreateCompilation(source); comp.MakeMemberMissing(WellKnownMember.System_Collections_Generic_List_T__ToArray); - // PROTOTYPE: Should report missing List.ToArray() for [..e] case only, not [..a]. + // https://github.com/dotnet/roslyn/issues/68785: Should not report missing List.ToArray() for [..a]. comp.VerifyEmitDiagnostics( // (9,13): error CS0656: Missing compiler required member 'System.Collections.Generic.List`1.ToArray' // b = [..a]; @@ -5041,7 +5183,7 @@ static void Main() } """; var comp = CreateCompilation(source); - // PROTOTYPE: // 2 should be reported as a warning (compare with array initializer: new object[] { null }). + // https://github.com/dotnet/roslyn/issues/68786: // 2 should be reported as a warning (compare with array initializer: new object[] { null }). comp.VerifyEmitDiagnostics( // (7,9): warning CS8602: Dereference of a possibly null reference. // x[0].ToString(); // 1 @@ -5147,16 +5289,16 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (13,24): error CS9500: Cannot initialize type 'S?' with a collection literal because the type is not constructible. + // (13,24): error CS9174: Cannot initialize type 'S?' with a collection literal because the type is not constructible. // S? x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S?").WithLocation(13, 24), - // (14,13): error CS9500: Cannot initialize type 'S?' with a collection literal because the type is not constructible. + // (14,13): error CS9174: Cannot initialize type 'S?' with a collection literal because the type is not constructible. // x = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S?").WithLocation(14, 13), - // (15,24): error CS9500: Cannot initialize type 'S?' with a collection literal because the type is not constructible. + // (15,24): error CS9174: Cannot initialize type 'S?' with a collection literal because the type is not constructible. // S? y = [1]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1]").WithArguments("S?").WithLocation(15, 24), - // (16,13): error CS9500: Cannot initialize type 'S?' with a collection literal because the type is not constructible. + // (16,13): error CS9174: Cannot initialize type 'S?' with a collection literal because the type is not constructible. // y = [2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[2]").WithArguments("S?").WithLocation(16, 13)); } @@ -5230,13 +5372,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (9,15): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (9,15): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // S s = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S").WithLocation(9, 15), - // (10,13): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (10,13): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("S").WithLocation(10, 13), - // (11,13): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (11,13): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = (S)([3, 4]); Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(S)([3, 4])").WithArguments("S").WithLocation(11, 13)); } @@ -5261,13 +5403,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (9,15): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (9,15): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // S s = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S").WithLocation(9, 15), - // (10,13): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (10,13): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = [1, 2]; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[1, 2]").WithArguments("S").WithLocation(10, 13), - // (11,13): error CS9500: Cannot initialize type 'S' with a collection literal because the type is not constructible. + // (11,13): error CS9174: Cannot initialize type 'S' with a collection literal because the type is not constructible. // s = (S)([3, 4]); Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(S)([3, 4])").WithArguments("S").WithLocation(11, 13)); } @@ -5468,10 +5610,10 @@ static void Main() """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics( - // (20,17): error CS9500: Cannot initialize type 'S2' with a collection literal because the type is not constructible. + // (20,17): error CS9174: Cannot initialize type 'S2' with a collection literal because the type is not constructible. // S2 v6 = []; Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "[]").WithArguments("S2").WithLocation(20, 17), - // (26,19): error CS9500: Cannot initialize type 'S2' with a collection literal because the type is not constructible. + // (26,19): error CS9174: Cannot initialize type 'S2' with a collection literal because the type is not constructible. // var v12 = (S2)([]); Diagnostic(ErrorCode.ERR_CollectionLiteralTargetTypeNotConstructible, "(S2)([])").WithArguments("S2").WithLocation(26, 19)); @@ -5519,13 +5661,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (6,17): error CS9503: There is no target type for the collection literal. + // (6,17): error CS9176: There is no target type for the collection literal. // var x = [default(TypedReference)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[default(TypedReference)]").WithLocation(6, 17), - // (7,17): error CS9503: There is no target type for the collection literal. + // (7,17): error CS9176: There is no target type for the collection literal. // var y = [default(ArgIterator)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[default(ArgIterator)]").WithLocation(7, 17), - // (8,17): error CS9503: There is no target type for the collection literal. + // (8,17): error CS9176: There is no target type for the collection literal. // var z = [default(RuntimeArgumentHandle)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[default(RuntimeArgumentHandle)]").WithLocation(8, 17)); } @@ -5550,10 +5692,10 @@ static void Main() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (10,17): error CS9503: There is no target type for the collection literal. + // (10,17): error CS9176: There is no target type for the collection literal. // var x = [default(R)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[default(R)]").WithLocation(10, 17), - // (11,17): error CS9503: There is no target type for the collection literal. + // (11,17): error CS9176: There is no target type for the collection literal. // var y = [new R(ref i)]; Diagnostic(ErrorCode.ERR_CollectionLiteralNoTargetType, "[new R(ref i)]").WithLocation(11, 17)); } @@ -5642,13 +5784,13 @@ static Expression>> Create2() """; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics( - // (13,22): error CS9501: An expression tree may not contain a collection literal. + // (13,22): error CS9175: An expression tree may not contain a collection literal. // return () => []; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionLiteral, "[]").WithLocation(13, 22), - // (17,22): error CS9501: An expression tree may not contain a collection literal. + // (17,22): error CS9175: An expression tree may not contain a collection literal. // return () => [1, 2]; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionLiteral, "[1, 2]").WithLocation(17, 22), - // (21,22): error CS9501: An expression tree may not contain a collection literal. + // (21,22): error CS9175: An expression tree may not contain a collection literal. // return () => [a, b]; Diagnostic(ErrorCode.ERR_ExpressionTreeContainsCollectionLiteral, "[a, b]").WithLocation(21, 22)); } @@ -6135,33 +6277,5 @@ static async Task F(T t) """; CompileAndVerify(new[] { source, s_collectionExtensions }, expectedOutput: "[3, 1, 2, 4], "); } - - [ConditionalFact(typeof(CoreClrOnly), AlwaysSkip = "PROTOTYPE: 'IAsyncEnumerable' does not contain a definition for 'GetAwaiter'")] - public void Async_03() - { - string source = """ - using System.Collections.Generic; - using System.Threading.Tasks; - class Program - { - static async Task Main() - { - (await F2(F1())).Report(); - } - static async IAsyncEnumerable F1() - { - await Task.Yield(); - yield return 1; - await Task.Yield(); - yield return 2; - } - static async Task F2(IAsyncEnumerable e) - { - return [3, .. await e, 4]; - } - } - """; - CompileAndVerify(new[] { source, s_collectionExtensions }, targetFramework: TargetFramework.Net70, expectedOutput: "[3, 1, 2, 4], "); - } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/CollectionLiteralParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/CollectionLiteralParsingTests.cs index 1bdfb8af58860..16d1c1066366c 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/CollectionLiteralParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/CollectionLiteralParsingTests.cs @@ -5330,8 +5330,7 @@ public void CastVersusIndexAmbiguity24_A() [Fact] public void CastVersusIndexAmbiguity24_B() { - // PROTOTYPE: No errors here syntactically. But user will likely get one semantically. - // + // No errors here syntactically. But user will likely get one semantically. // We may want a dedicated error to tell them to parenthesize the brackets if they're trying to cast this as a list. UsingExpression("(A)[1]"); @@ -5365,8 +5364,8 @@ public void CastVersusIndexAmbiguity24_B() [Fact] public void CastVersusIndexAmbiguity24_C() { - // PROTOTYPE: This is not a great diagnostic. Users could easily run into this and be confused. Can we do - // better. For example: + // This is not a great diagnostic. Users could easily run into this and be confused. Can we do + // better. For example: // // 1. tell them we think this is an indexer, and `1:2` isn't a valid argument. // 2. tell them to parenthesize the brackets if they're trying to cast this as a list. @@ -5416,7 +5415,7 @@ public void CastVersusIndexAmbiguity24_C() [Fact] public void CastVersusIndexAmbiguity24_D() { - // PROTOTYPE: No errors here syntactically. But user will likely get one semantically. Specifically, this + // No errors here syntactically. But user will likely get one semantically. Specifically, this // could look like a case of a collection literal with a spread element in it, or as indexing into a // parenthesized expression with a range expression. //