Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions standard/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ A number of attributes affect the language in some way. These attributes include
- `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` and `System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute`, which are used to declare a custom interpolated string expression handler ([§23.5.11.1](attributes.md#235111-custom-interpolated-string-expression-handlers)) and to call one of its constructors, respectively.
- `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute` ([§23.5.8](attributes.md#2358-the-unscopedref-attribute)), which allows an otherwise implicitly scoped ref to be treated as not being scoped.
- `System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute` ([§23.5.12.1](attributes.md#235121-the-setsrequiredmembers-attribute)) and `System.Runtime.CompilerServices.RequiredMemberAttribute` ([§23.5.12.2](attributes.md#235122-the-requiredmember-attribute)), which are used in required-member contexts ([§15.7.1](classes.md#1571-general)).
- `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute), which marks a struct type as an inline array type (§InlineArray).

The Nullable static analysis attributes ([§23.5.7](attributes.md#2357-code-analysis-attributes)) can improve the correctness of warnings generated for nullabilities and null states ([§8.9.5](types.md#895-nullabilities-and-null-states)).

Expand Down Expand Up @@ -1577,6 +1578,10 @@ This attribute indicates that the constructor it decorates sets all required mem

This attribute indicates that the current type has one or more required members ([§15.7.1](classes.md#1571-general)), or that a specific member of that type is required. However, it is an error for this attribute to be used explicitly. Instead, the presence of the modifier `required` results in the type or member being treated as if it were decorated with this attribute.

### §InlineArrayAttribute The InlineArray attribute

This attribute is used to identify a non-record struct as an inline array type. For further information and examples of its use, see §InlineArray.

## 23.6 Attributes for interoperation

For interoperation with other languages, an indexer may be implemented using indexed properties. If the indexer is not decorated with `IndexerNameAttribute`, then the name `Item` is used by default. `IndexerNameAttribute` enables a developer to override this default and specify a different name.
Expand Down
11 changes: 11 additions & 0 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
> ```csharp
> enum Color { Red, Blue, Green }
>
> // The expression 0 converts implicitly to enum types

Check warning on line 28 in standard/conversions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/conversions.md#L28

MDC032::Line length 82 > maximum 81
> Color c0 = 0;
>
> // Other int expressions need explicit conversion
Expand Down Expand Up @@ -460,6 +460,16 @@
>
> *end example*

### §ImplicitInlineArrayConversions Implicit inline array conversions

The implicit inline array (§InlineArray) conversions are:

- From an expression designating a writable inline array with element type `T` to `System.Span<T>`
- From an expression designating a writable inline array with element type `T` to `System.ReadonlySpan<T>`
- From an expression designating a readonly inline array with element type `T` to `System.ReadonlySpan<T>`

The conversion of an inline array to a `System.Span` or `System.ReadonlySpan` ignores any declared operators in the inline array type that might otherwise appear to be applicable. See §InlineArray for more information.
Comment on lines +468 to +471

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be ReadOnlySpan with capital O.


## 10.3 Explicit conversions

### 10.3.1 General
Expand Down Expand Up @@ -704,6 +714,7 @@
- Boxing conversions ([§10.2.9](conversions.md#1029-boxing-conversions))
- Implicit constant expression conversions ([§10.2.11](conversions.md#10211-implicit-constant-expression-conversions))
- Implicit conversions involving type parameters ([§10.2.12](conversions.md#10212-implicit-conversions-involving-type-parameters))
- Implicit inline array conversions (§ImplicitInlineArrayConversions)

The standard implicit conversions specifically exclude user-defined implicit conversions.

Expand Down
157 changes: 155 additions & 2 deletions standard/expressions.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# 12 Expressions

Check warning on line 1 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1

MDC032::Line length 83 > maximum 81

Check warning on line 1 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L1

MDC032::Line length 84 > maximum 81

Check warning on line 2 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2

MDC032::Line length 84 > maximum 81

Check warning on line 2 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L2

MDC032::Line length 85 > maximum 81
## 12.1 General

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 85 > maximum 81

Check warning on line 3 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L3

MDC032::Line length 86 > maximum 81

An expression is a sequence of operators and operands. This clause defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

Check warning on line 5 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5

MDC032::Line length 82 > maximum 81

Check warning on line 5 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L5

MDC032::Line length 102 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 97 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81

Check warning on line 6 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L6

MDC032::Line length 82 > maximum 81
An expression *E* is said to ***directly contain*** a subexpression *E₁* if it is not subject to a user-defined conversion [§10.5](conversions.md#105-user-defined-conversions) whose parameter is not of a non-nullable value type, and one of the following conditions holds:

Check warning on line 8 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L8

MDC032::Line length 90 > maximum 81
- *E* is *E₁*.
- If *E* is a parenthesized expression `(E₂)`, and *E₂* directly contains *E₁*.
- If *E* is a null-forgiving operator expression `E₂!`, and *E₂* directly contains *E₁*.
- If *E* is a cast expression `(T)E₂`, and the cast does not subject *E₂* to a non-lifted user-defined conversion whose parameter is not of a non-nullable value type, and *E₂* directly contains *E₁*.

Check warning on line 12 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L12

MDC032::Line length 82 > maximum 81

## 12.2 Expression classifications

Expand All @@ -28,7 +28,7 @@

For expressions which occur as subexpressions of larger expressions, with the noted restrictions, the result can also be classified as one of the following:

- A namespace. An expression with this classification can only appear as the left-hand side of a *member_access* ([§12.8.7](expressions.md#1287-member-access)). In any other context, an expression classified as a namespace causes a compile-time error.

Check warning on line 31 in standard/expressions.md

View workflow job for this annotation

GitHub Actions / Markdown to Word Converter

standard/expressions.md#L31

MDC032::Line length 82 > maximum 81
- A type. An expression with this classification can only appear as the left-hand side of a *member_access* ([§12.8.7](expressions.md#1287-member-access)). In any other context, an expression classified as a type causes a compile-time error.
- A method group, which is a set of overloaded methods resulting from a member lookup ([§12.5](expressions.md#125-member-lookup)). A method group may have an associated instance expression and an associated type argument list. When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§12.8.14](expressions.md#12814-this-access)). A method group is permitted in an *invocation_expression* ([§12.8.10](expressions.md#12810-invocation-expressions)) or a *delegate_creation_expression* ([§12.8.17.5](expressions.md#128175-delegate-creation-expressions)), and can be implicitly converted to a compatible delegate type ([§10.8](conversions.md#108-method-group-conversions)). In any other context, an expression classified as a method group causes a compile-time error.
- An event access. Every event access has an associated type, namely the type of the event. Furthermore, an event access may have an associated instance expression. An event access may appear as the left operand of the `+=` and `-=` operators ([§12.24.6](expressions.md#12246-event-assignment)). In any other context, an expression classified as an event access causes a compile-time error. When an accessor of an instance event access is invoked, the result of evaluating the instance expression becomes the instance represented by `this` ([§12.8.14](expressions.md#12814-this-access)).
Expand Down Expand Up @@ -2420,7 +2420,7 @@
An *element_access* is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)) if at least one of the following holds:

- The *primary_expression* has compile-time type `dynamic`.
- At least one expression of the *argument_list* has compile-time type `dynamic`.
- At least one expression of the *argument_list* has compile-time type `dynamic`, and the *primary_no_array_creation_expression* does not have an inline array type (§InlineArray) or there is more than one *argument* in the *argument_list*.

In this case the compile-time type of the *element_access* depends on the compile-time type of its *primary_expression*: if it has an array type then the compile-time type is the element type of that array type; otherwise the compile-time type is `dynamic` and the *element_access* is classified as a value of type `dynamic`. The rules below to determine the meaning of the *element_access* are then applied at run-time, using the run-time type instead of the compile-time type of those of the *primary_expression* and *argument_list* expressions which have the compile-time type `dynamic`. If the *primary_expression* does not have compile-time type `dynamic`, then the element access undergoes a limited compile-time check as described in [§12.6.5](expressions.md#1265-compile-time-checking-of-dynamic-member-invocation).

Expand All @@ -2436,14 +2436,16 @@
>
> *end example*

If the *primary_expression* of an *element_access* is:
If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access)). Otherwise, if the *primary_no_array_creation_expression* of an *element_access* is a variable or value of an inline array type and the *argument_list* consists of a single argument, the *element_access* is an inline array element access (§InlineArrayElementAccess). Otherwise, the *primary_no_array_creation_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)).

- a value of an array type, the *element_access* is an array access ([§12.8.12.2](expressions.md#128122-array-access));
- a value of `string` type, the *element_access* is a string access ([§12.8.12.3](expressions.md#128123-string-access));
- otherwise, the *primary_expression* shall be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the *element_access* is an indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)).

#### 12.8.12.2 Array access

For access to elements in an inline array (§InlineArray) see §InlineArrayElementAccess.

For an array access the *argument_list* shall not contain named arguments or by-reference arguments ([§15.6.2.3](classes.md#15623-by-reference-parameters)).

The number of expressions in the *argument_list* shall be the same as the rank of the *array_type*, and each expression shall be:
Expand Down Expand Up @@ -2477,6 +2479,157 @@
- The value of each expression in the *argument_list* is checked against the actual bounds of each dimension of the array instance referenced by `P`. If one or more values are out of range, a `System.IndexOutOfRangeException` is thrown and no further steps are executed.
- The variable reference of the array element given by the index expressions is computed, and this becomes the result of the array access.

#### §InlineArrayElementAccess Inline array element access

For access to an element in an inline array (§InlineArray), the *primary_no_array_creation_expression* of the *element_access* shall designate an inline array. Furthermore, the *argument_list* shall contain a single *argument*, which is not a named argument ([§12.6.2.1](expressions.md#12621-general)). That *argument* shall be of type `int`, or be implicitly convertible to type `int`, `System.Index`, or `System.Range`.

It is a compile-time error if *argument* is a constant expression whose value results in an index outside the bounds of the inline array. If at runtime the value of *argument* results in an index outside the bounds of the inline array, a `System.IndexOutOfRangeException` is thrown.

**When *argument*’s type is `int`**

If *primary_no_array_creation_expression* is a writable variable, the result of evaluating an inline array element access is a writable variable equivalent to invoking the indexer

```csharp
public ref T this[int index] { get; }
```

with *argument* as the index, on an instance of `System.Span<T>` that was created from the inline array designated by *primary_no_array_creation_expression*. For the purpose of ref-safety analysis, the safe-context ([§9.7.2.1](variables.md#9721-general)) of the access is equivalent to that for an invocation of a method with the signature

```csharp
static ref T GetItem(ref «InlineArrayType» array)
```

The resulting variable is considered movable if and only if *primary_no_array_creation_expression* is movable.

If *primary_no_array_creation_expression* is a readonly variable, the result of evaluating an inline array element access is a readonly variable equivalent to invoking the indexer

```csharp
public ref readonly T this[int index] { get; }
```

with *argument* as the index, on an instance of `System.ReadOnlySpan<T>` that was created from the inline array designated by *primary_no_array_creation_expression*. For the purpose of ref-safety analysis, the safe-context of the access is equivalent to that for an invocation of a method with the signature

```csharp
static ref readonly T GetItem(in «InlineArrayType» array)
```

The resulting variable is considered movable if and only if *primary_no_array_creation_expression* is movable.

If *primary_no_array_creation_expression* is a value, the result of evaluating an inline array element access is a value equivalent to invoking the indexer

```csharp
public ref readonly T this[int index] { get; }
```

with *argument* as the index, on an instance of `System.ReadOnlySpan<T>` that was created from the inline array designated by *primary_no_array_creation_expression*. For the purpose of ref-safety analysis the safe-context of the access are equivalent to that for an invocation of a method with the signature

```csharp
static T GetItem(«InlineArrayType» array)
```

> *Example*:
> <!-- Example: {template:"standalone-lib-without-using", name:"InlineArays1", expectedErrors:["CS8329","CS8156","CS1510"]} -->
>
> ```csharp
> [System.Runtime.CompilerServices.InlineArray(10)]
> public struct Buffer10<T>
> {
> private T _element0;
> }
> public class Program
> {
> void M1(Buffer10<int> x)
> {
> ref int a = ref x[0]; // OK
> }
> void M2(in Buffer10<int> x)
> {
> ref readonly int a = ref x[0]; // OK
> ref int b = ref x[0]; // Error; x is readonly
> }
> Buffer10<int> GetBuffer() => default;
> void M3()
> {
> int a = GetBuffer()[0]; // OK
> ref readonly int b = ref GetBuffer()[0];// Error, rhs is a value
> ref int c = ref GetBuffer()[0]; // Error; rhs is a value
> }
> }
> ```
>
> *end example*

**When *argument*’s type is implicitly convertible to `int`**

The value of *argument* is converted to `int` and the element access is interpreted as described when *argument*’s type is `int`

**When *argument*’s type is implicitly convertible to `System.Index`**

*argument* is converted to `System.Index` and then to an `int`-based index value indicating the element position relative to the start of the inline array. Then, the element access is interpreted as described when *argument*’s type is `int`.

Using an index of `System.Index` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Index`. Specifically, an inline array element access ignores any declared indexers in the inline array type. See §InlineArray for more information.

**When *argument*’s type is implicitly convertible to `System.Range`**

If *primary_no_array_creation_expression* is a writable variable, the result of evaluating an inline array element access is a variable equivalent to invoking the method

```csharp
public Span<T> Slice (int start, int length)
```

passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.Span<T>` that was created from the inline array designated by *primary_no_array_creation_expression*. For the purpose of ref-safety analysis, the safe-context ([§9.7.2.1](variables.md#9721-general)) of the access is equivalent to that for an invocation of a method with the signature

```csharp
static System.Span<T> GetSlice(ref «InlineArrayType» array)
```

If *primary_no_array_creation_expression* is a readonly variable, the result of evaluating an inline array element access is a value equivalent to invoking the method

```csharp
public ReadOnlySpan<T> Slice (int start, int length)
```

passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.ReadOnlySpan<T>` that was created from the inline array designated by *primary_no_array_creation_expression*. For the purpose of ref-safety analysis, the safe-context of the access is equivalent to that for an invocation of a method with the signature

```csharp
static System.ReadOnlySpan<T> GetSlice(in «InlineArrayType» array)
```

Using an index of `System.Range` to access an element in a non-inline array is described in [§12.8.12.2](expressions.md#128122-array-access). However, note carefully that that process is *not* used when an inline array is indexed using a `System.Range`. Specifically, an inline array element access ignores any declared Slice methods in the inline array type. See §InlineArray for more information.

If *primary_no_array_creation_expression* is a value, an error is reported.

> *Example*:
>
> <!-- Example: {template:"standalone-lib-without-using", name:"InlineArays2", expectedErrors:["CS0029","CS8156"]} -->
>
> ```csharp
> [System.Runtime.CompilerServices.InlineArray(10)]
> public struct Buffer10<T>
> {
> private T _element0;
> }
> public class Program
> {
> void M1(Buffer10<int> x)
> {
> System.Span<int> a = x[..]; // OK
> }
> void M2(in Buffer10<int> x)
> {
> System.ReadOnlySpan<int> a = x[..]; // OK
> System.Span<int> b = x[..]; // Error; no implicit conversion
> }
> Buffer10<int> GetBuffer() => default;
> void M3()
> {
> _ = GetBuffer()[..]; // Error; rhs is a value
> }
> }
> ```
>
> *end example*

#### 12.8.12.3 String access

For a string access the *argument_list* of the *element_access* shall contain a single unnamed value argument ([§15.6.2.2](classes.md#15622-value-parameters)) which shall be:
Expand Down
9 changes: 9 additions & 0 deletions standard/standard-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,14 @@ namespace System.Runtime.CompilerServices
void UnsafeOnCompleted(Action continuation);
}

[AttributeUsage(AttributeTargets.Struct, AllowMultiple=false)]
public sealed class InlineArrayAttribute : Attribute
{
public InlineArrayAttribute(int length);

public int Length { get; }
}

public interface INotifyCompletion
{
void OnCompleted(Action continuation);
Expand Down Expand Up @@ -1532,6 +1540,7 @@ The following library types are referenced in this specification. The full names
- `global::System.Runtime.CompilerServices.FormattableStringFactory`
- `global::System.Runtime.CompilerServices.ICriticalNotifyCompletion`
- `global::System.Runtime.CompilerServices.IndexerNameAttribute`
- `global::System.Runtime.CompilerServices.InlineArrayAttribute`
- `global::System.Runtime.CompilerServices.INotifyCompletion`
- `global::System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute`
- `global::System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute`
Expand Down
Loading
Loading