Skip to content

Public API changes for InlineArrays feature #68719

@AlekseyTs

Description

@AlekseyTs
namespace Microsoft.CodeAnalysis
{
    /// <summary>
    /// All of the kinds of operations, including statements and expressions.
    /// </summary>
    public enum OperationKind
    {
+        /// <summary>Indicates an <see cref="IInlineArrayAccessOperation"/>.</summary>
+        InlineArrayAccess = 0x7e,
    }
}

namespace Microsoft.CodeAnalysis.Operations
{
    /// <summary>
    /// Represents a reference to an array element.
    /// <para>
    /// Current usage:
    ///  (1) C# array element reference expression.
    ///  (2) VB array element reference expression.
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>This node is associated with the following operation kinds:</para>
    /// <list type="bullet">
    /// <item><description><see cref="OperationKind.ArrayElementReference"/></description></item>
    /// </list>
    /// <para>This interface is reserved for implementation by its associated APIs. We reserve the right to
    /// change it in the future.</para>
    /// </remarks>
    public interface IArrayElementReferenceOperation : IOperation
    {
        /// <summary>
        /// Array to be indexed.
        /// </summary>
        IOperation ArrayReference { get; }
        /// <summary>
        /// Indices that specify an individual element.
        /// </summary>
        ImmutableArray<IOperation> Indices { get; }
    }

    /// <summary>
    /// Represents a reference to an implicit System.Index or System.Range indexer over a non-array type.
    /// <para>
    ///   Current usage:
    ///   (1) C# implicit System.Index or System.Range indexer reference expression.
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>This node is associated with the following operation kinds:</para>
    /// <list type="bullet">
    /// <item><description><see cref="OperationKind.ImplicitIndexerReference"/></description></item>
    /// </list>
    /// <para>This interface is reserved for implementation by its associated APIs. We reserve the right to
    /// change it in the future.</para>
    /// </remarks>
    public interface IImplicitIndexerReferenceOperation : IOperation
    {
        /// <summary>
        /// Instance of the type to be indexed.
        /// </summary>
        IOperation Instance { get; }
        /// <summary>
        /// System.Index or System.Range value.
        /// </summary>
        IOperation Argument { get; }
        /// <summary>
        /// The <c>Length</c> or <c>Count</c> property that might be used to fetch the length value.
        /// </summary>
        ISymbol LengthSymbol { get; }
        /// <summary>
        /// Symbol for the underlying indexer or a slice method that is used to implement the implicit indexer.
        /// </summary>
        ISymbol IndexerSymbol { get; }
    }

+    /// <summary>
+    /// Represents an element reference or a slice operation over an inline array type.
+    /// <para>
+    ///   Current usage:
+    ///   (1) C# inline array access.
+    /// </para>
+    /// </summary>
+    /// <remarks>
+    /// <para>This node is associated with the following operation kinds:</para>
+    /// <list type="bullet">
+    /// <item><description><see cref="OperationKind.InlineArrayAccess"/></description></item>
+    /// </list>
+    /// <para>This interface is reserved for implementation by its associated APIs. We reserve the right to
+    /// change it in the future.</para>
+    /// </remarks>
+    public interface IInlineArrayAccessOperation : IOperation
+    {
+        /// <summary>
+        /// Instance of the inline array type to be accessed.
+        /// </summary>
+        IOperation Instance { get; }
+        /// <summary>
+        /// System.Int32, System.Index or System.Range value.
+        /// </summary>
+        IOperation Argument { get; }
+    }

    public abstract partial class OperationVisitor
    {
+        public virtual void VisitInlineArrayAccess(IInlineArrayAccessOperation operation) => DefaultVisit(operation);
    }

    public abstract partial class OperationVisitor<TArgument, TResult>
    {
+        public virtual TResult? VisitInlineArrayAccess(IInlineArrayAccessOperation operation, TArgument argument) => DefaultVisit(operation, argument);
    }
}

Alternatively, we could reuse IArrayElementReferenceOperation. However inline array access doesn't always represent an element access. Some access represents a slice operation. Also, there is never more than one argument/index. I feel that IImplicitIndexerReferenceOperation is a closer alternative. However, given special semantics around inline array access and the fact that Length and indexer symbols are never involved (whereas they are always involved for IImplicitIndexerReferenceOperation) I think that users will be served better with a dedicated node, that reuses some of the members from IImplicitIndexerReferenceOperation.

namespace Microsoft.CodeAnalysis
{
    /// <summary>
    /// Specifies capabilities that may or may not be supported by the common language runtime the compilation is
    /// targeting.
    /// </summary>
    public enum RuntimeCapability
    {
+        /// <summary>
+        /// Indicates that this version of runtime supports inline array types.
+        /// </summary>
+        InlineArrayTypes = 7
    }
}
namespace Microsoft.CodeAnalysis
{
    /// <summary>
    /// Specifies the Ids of special runtime types.
    /// </summary>
    /// <remarks>
    /// Only types explicitly mentioned in "Co-located core types" spec 
    /// (https://github.com/dotnet/roslyn/blob/main/docs/compilers/Co-located%20core%20types.md)
    /// can be in this enum.
    /// The following things should be in sync:
    ///     1) SpecialType enum
    ///     2) names in SpecialTypes.EmittedNames array.
    /// </remarks>
    public enum SpecialType : sbyte
    {
        /// <summary>
        /// An attribute that is placed on each method with a 'methodimpl" aka ".override" in metadata.
        /// </summary>
        System_Runtime_CompilerServices_PreserveBaseOverridesAttribute = 45,

+        /// <summary>
+        /// An attribute that is placed on an inline array type.
+        /// </summary>
+        System_Runtime_CompilerServices_InlineArrayAttribute = 46,

        /// <summary>
        /// Count of special types. This is not a count of enum members.
        /// </summary>
-        Count = System_Runtime_CompilerServices_PreserveBaseOverridesAttribute
+        Count = System_Runtime_CompilerServices_InlineArrayAttribute
}
namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// Summarizes whether a conversion is allowed, and if so, which kind of conversion (and in some cases, the
    /// associated symbol).
    /// </summary>
    public readonly struct Conversion : IEquatable<Conversion>, IConvertibleConversion
    {
+        /// <summary>
+        /// Returns true if the conversion is an inline array conversion.
+        /// </summary>
+        public bool IsInlineArray
+        {
+            get
+            {
+                return Kind == ConversionKind.InlineArray;
+            }
+        }
    }
}

Metadata

Metadata

Assignees

Labels

Area-CompilersConcept-APIThis issue involves adding, removing, clarification, or modification of an API.Feature - Inline Arraysapi-approvedAPI was approved in API review, it can be implemented

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions