-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Closed
Labels
Concept-APIThis issue involves adding, removing, clarification, or modification of an API.This issue involves adding, removing, clarification, or modification of an API.Feature - Collection ExpressionsFeature Requestapi-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implemented
Milestone
Description
Background and Motivation
Provide IOperation support for collection expressions.
Proposed API
namespace Microsoft.CodeAnalysis.Operations
{
/// <summary>
/// Represents a collection expression.
/// <para>
/// Current usage:
/// (1) C# collection expression.
/// </para>
/// </summary>
public interface ICollectionExpressionOperation : IOperation
{
/// <summary>
/// Method used to construct the collection.
/// <para>
/// If the collection type is an array, span, array interface, or type parameter, the method is null;
/// if the collection type has a [CollectionBuilder] attribute, the method is the builder method;
/// otherwise, the method is the collection type constructor.
/// </para>
/// </summary>
IMethodSymbol? ConstructMethod { get; }
/// <summary>
/// Collection expression elements.
/// <para>
/// If the element is an expression, the entry is converted to the target element type;
/// otherwise, the entry is an ISpreadOperation.
/// </para>
/// </summary>
ImmutableArray<IOperation> Elements { get; }
}
/// <summary>
/// Represents a collection expression spread element.
/// <para>
/// Current usage:
/// (1) C# spread element.
/// </para>
/// </summary>
public interface ISpreadOperation : IOperation
{
/// <summary>
/// Collection being spread.
/// </summary>
IOperation Operand { get; }
/// <summary>
/// Type of the collection iterator item.
/// </summary>
ITypeSymbol ItemType { get; }
/// <summary>
/// Conversion from the type of the iterator item to the target element type
/// of the containing collection expression.
/// </summary>
CommonConversion ItemConversion { get; }
}
}
namespace Microsoft.CodeAnalysis.CSharp
{
public readonly struct Conversion
{
// ...
public bool IsCollectionExpression { get; }
}
public static class CSharpExtensions
{
// ...
/// <summary>
/// Gets the underlying item <see cref="Conversion"/> information from this <see cref="ISpreadOperation"/>.
/// </summary>
public static Conversion GetSpreadItemConversion(this ISpreadOperation spread);
}
}Usage Examples
Span:
// Span<object> x = [1];
ICollectionExpressionOperation (1 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: System.Span<System.Object>) (Syntax: '[1]')
Elements(1):
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '1')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Collection initializer type:
// List<object> x = [1];
ICollectionExpressionOperation (1 elements, ConstructMethod: System.Collections.Generic.List<System.Object>..ctor()) (OperationKind.CollectionExpression, Type: System.Collections.Generic.List<System.Object>) (Syntax: '[1]')
Elements(1):
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '1')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Builder method:
// MyCollection<object> x = [1];
// [CollectionBuilder(typeof(MyCollectionBuilder), "Create")]
// struct MyCollection<T> : IEnumerable<T> { ... }
// class MyCollectionBuilder
// {
// public static MyCollection<T> Create<T>(ReadOnlySpan<T> items) { ... }
// }
ICollectionExpressionOperation (1 elements, ConstructMethod: MyCollection<System.Object> MyCollectionBuilder.Create<System.Object>(System.ReadOnlySpan<System.Object> items)) (OperationKind.CollectionExpression, Type: MyCollection<System.Object>) (Syntax: '[1]')
Elements(1):
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '1')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Spread:
// int[] x = ...;
// object[] y = [..x];
ICollectionExpressionOperation (1 elements, ConstructMethod: null) (OperationKind.CollectionExpression, Type: System.Object[]) (Syntax: '[..x]')
Elements(1):
ISpreadOperation (ItemType: System.Int32) (OperationKind.Spread, Type: null, IsImplicit) (Syntax: '..x')
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32[]) (Syntax: 'x')
ItemConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
(Boxing)
Alternative Designs
Risks
Relates to test plan: #66418
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Concept-APIThis issue involves adding, removing, clarification, or modification of an API.This issue involves adding, removing, clarification, or modification of an API.Feature - Collection ExpressionsFeature Requestapi-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implemented