Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test plan for "collection literals" #66418

Closed
jcouv opened this issue Jan 13, 2023 · 0 comments
Closed

Test plan for "collection literals" #66418

jcouv opened this issue Jan 13, 2023 · 0 comments

Comments

@jcouv
Copy link
Member

jcouv commented Jan 13, 2023

The feature was renamed to "collection expressions".
Championed issue: dotnet/csharplang#5354
Speclet: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md

Compiler

General Concerns

Parsing

  • Ambiguity scenarios
    • a?[b] (CollectionExpressionParsingTests.ConditionalAmbiguityX)
    • Attribute/collection literal confusion (CollectionExpressionParsingTests.AttributeOnStartOfLambda, CollectionExpressionParsingTests.TopLevelDotAccess_AttributeAmbiguityX)
    • Cast vs parenthesized expression (CollectionExpressionParsingTests.CastVsIndexAmbiguityX)
      • (a)[b]
      • (a?)[b]
      • (a<b>)[c]
    • Breaking change: _ = x ? y?[0] : z; // syntax error
  • As RValue
    • Indexing expression (CollectionExpressionParsingTests.AttemptToImmediatelyIndexInTopLevelStatement)
    • Direct invocation
    • Input to switch expression
    • Empty collection
    • Operators

Semantics

  • Definite assignment
  • Test in catch filter
    • Particularly with something that might require multiple spill levels, such as interpolated string handler element type
  • Usage in async methods
    • When builder type is a ref struct and there are no awaits in the elements
    • When builder type is a ref struct and there are awaits in the elements
      • With fallback ability (List)
      • Without fallback ability
  • Best common element type (BestCommonType_03, _04)
  • Type Inference:
    • Usage in generic arguments makes inferences from collection literal elements (TypeInference_03, _04)
    • Usage in lambda returns makes inferences from collection literal elements
    • Tuples of collection literals
    • Collection literals of tuples (TypeInference_37)
  • Target types:
    • var, object, dynamic
    • T[] (Array_*)
    • T[,] (Array_04)
    • Span<T>, ReadOnlySpan<T> (Span_*)
    • IEnumerable, ICollection, IList (InterfaceType_01)
    • IEnumerable<T>, ICollection<T>, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T> (InterfaceType_02)
    • collection initializer types: reference type, value type, type parameter (CollectionInitializerType_01, _02, TypeParameter_*)
    • custom construct methods
    • inline arrays
    • Element type has conversion from expression, like interpolated string handlers
  • Collection initializer types:
    • 0, 1, >1 Add() method (CollectionInitializerType_03, CollectionInitializerType_12)
    • inaccessible .ctor (CollectionInitializerType_05)
    • .ctor with/without int capacity
    • .ctor with all optional parameters (CollectionInitializerType_ConstructorOptionalParameters)
    • .ctor with single params parameter (CollectionInitializerType_ConstructorParamsArray)
    • .ctor with ref parameters
    • ref struct element type (RefStruct_03)
    • Obsolete methods
    • UnmanagedCallersOnly methods
    • CompilerFeatureRequired methods
    • Nullability mismatches
    • Collection builder type is a PIA
  • Spread collection type:
    • IEnumerable only (SpreadElement_10)
    • pattern-based enumerator
      • Without implementing IDisposable
      • With implementing IDisposable
    • ref struct iterator type
    • ref struct type
      • Without Dispose
      • With Dispose
    • with Length or Count property
    • Above marked Obsolete (SpreadElement_LengthObsolete)
    • Above marked UnmanagedCallersOnly
    • Above marked CompilerFeatureRequired
    • Embeds appropriate interop types when enumerator is an pia
  • Extension method invocation
    • type inference
      methods)
  • cannot be used as constants
  • Expression trees (ExpressionTrees)
  • Optimizations:
    • emit Array.Empty<T>() for IEnumerable<T> e = []; (ArrayEmpty_01)
    • avoid heap allocation when not observable: foreach (var b in [true, false]) { ... }
  • __arglist and ArgIterator usage
  • ref safety in elements
    • Element should not escape by value
    • Element should not escape by ref
    • stackalloc element
    • collection expressions targeting ref structs cannot be returned (RefSafety_Return_01)
  • Use as LValue
    • Directly assigning
    • Assigning into an indexer
    • Pass by ref (readonly)
    • Pass by in
      • Implicit (TypeInference_20)
      • Explicit (TypeInference_21)
    • ref (readonly) return
    • ref reassignment
  • Anonymous type usage
    • Assignment to property
    • Top-level usage
  • Direct slicing (1..2)
  • Direct indexing (^1)
  • Execution order of elements vs collection ctor
  • Direct method execution (MemberAccess_01, _02)
  • fixed statement immediately taking a pointer
  • Direct argument of a using block
  • Collection element subjected to a checked user-defined implicit conversion during creation
  • ReadOnlySpan<byte[]> x = ["abc"u8]; should behave like byte[] x = "abc"u8;
  • Suppression with ! (should produce a diagnostic)
  • Nullability analysis

Productivity

  • Completion
    • Verify that completion for [return: MyAttribute] and [return: expr] are both possible
  • Formatting: List<int> list = [1, 2, 3]; (no extra spaces)
  • Incomplete code typing experience
  • Find all on builder types/methods
  • F1 on the brackets
  • Immediate window compilation
  • DebuggerDisplay
  • Assigning values in the watch window
  • EE
  • EnC
  • Stepping through debugger with [Method1(), Method2()] should behave like array creation and other similar existing constructs

Open Questions

  • Syntax ambiguities:
    • (X)[i] cast collection literal or indexing?
    • [a ? [b] : c] conditional [a ? ([b]) : c] or key-value pair [(a ? [b]) : c]?
    • a ? b ? [c] : d nested indexer a ? (b?[c]) : d or nested collection literal a ? (b ? ([c]) : d)?
    • Range[] ranges = [range1, ..e, range2]; spread or range ..e?
  • Collection literals at the beginning of an expression statement?
    [1].ToString(); // error CS7014: Attributes are not valid in this context.
  • What are the requirements for a spread element type? Is a span spreadable for instance?
  • Is evaluation of elements interleaved with Add() calls?
  • Any type that implements IEnumerable and has an accessible parameterless constructor is a valid target type for []. Should the requirements for a collection initializer type be stronger than this?
  • Should multi-dimensional arrays be supported with nested collection literal syntax?
    int[,] a = [[1, 2], [3, 4]];
  • Should better function member prefer some constructible collection types over others?
    F([1, 2, 3]); // ambiguous?
    
    static void F(IEnumerable<int> arg) { }
    static void F(int[] arg) { }
  • When generating an intermediate List, should we use the well-known member List<T>.Add(T) rather than relying on lookup?
  • Should spread elements support target type?
    string[] a = [..b ? [null] : []];
  • Infer from spread element iteration type? See LDM-2023-09-20
    IEnumerable<int> e = [1, 2, 3];
    F([..e]);     // ok?
    F([..[4, 5]); // ok?
    
    static void F<T>(T[] arg) { }
  • Infer from lambda return expression? From 11.6.3.7, a lower-bound inference is made from the return type of the lambda expression. (TypeInference_40)
    F(() => [1]);
    F(() => { if (b) return []; return [2]; });
    
    static void F<T>(Func<T[]> arg) { }
  • Should IAsyncEnumerable<int> e be supported for [1, 2, await ..e]?
@jcouv jcouv added this to the C# 12.0 milestone Jan 13, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Jan 13, 2023
@jcouv jcouv removed the untriaged Issues and PRs which have not yet been triaged by a lead label Jan 13, 2023
@jaredpar jaredpar modified the milestones: C# 12.0, 17.8 Sep 11, 2023
@jcouv jcouv modified the milestones: 17.8, 17.9 Oct 11, 2023
@jaredpar jaredpar modified the milestones: 17.9, .NET 8 Nov 2, 2023
@jaredpar jaredpar closed this as completed Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants