Permit stackalloc in nested contexts

Note

This article is a feature specification. The specification serves as the design document for the feature. It includes proposed specification changes, along with information needed during the design and development of the feature. These articles are published until the proposed spec changes are finalized and incorporated in the current ECMA specification.

There may be some discrepancies between the feature specification and the completed implementation. Those differences are captured in the pertinent language design meeting (LDM) notes.

You can learn more about the process for adopting feature speclets into the C# language standard in the article on the specifications.

Stack allocation

We modify the section Stack allocation (ยง22.9) of the C# language specification to relax the places when a stackalloc expression may appear. We delete

local_variable_initializer_unsafe
    : stackalloc_initializer
    ;

stackalloc_initializer
    : 'stackalloc' unmanaged_type '[' expression ']'
    ;

and replace them with

primary_no_array_creation_expression
    : stackalloc_initializer
    ;

stackalloc_initializer
    : 'stackalloc' unmanaged_type '[' expression? ']' array_initializer?
    | 'stackalloc' '[' expression? ']' array_initializer
    ;

Note that the addition of an array_initializer to stackalloc_initializer (and making the index expression optional) was an extension in C# 7.3 and is not described here.

The element type of the stackalloc expression is the unmanaged_type named in the stackalloc expression, if any, or the common type among the elements of the array_initializer otherwise.

The type of the stackalloc_initializer with element type K depends on its syntactic context:

  • If the stackalloc_initializer appears directly as the local_variable_initializer of a local_variable_declaration statement or a for_initializer, then its type is K*.
  • Otherwise its type is System.Span<K>.

Stackalloc Conversion

The stackalloc conversion is a new built-in implicit conversion from expression. When the type of a stackalloc_initializer is K*, there is an implicit stackalloc conversion from the stackalloc_initializer to the type System.Span<K>.