From c0cd67ea6e3bfc72faba637468b2ecb3c8b0ebb9 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:10:44 -0400 Subject: [PATCH 01/19] Add inline array feature --- standard/conversions.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/standard/conversions.md b/standard/conversions.md index 4a50a8712..569943084 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -460,6 +460,16 @@ Although an implicit conversion to `object` is permitted, a warning shall be iss > > *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` +- From an expression designating a writable inline array with element type `T` to `System.ReadonlySpan` +- From an expression designating a readonly inline array with element type `T` to `System.ReadonlySpan` + +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.] + ## 10.3 Explicit conversions ### 10.3.1 General From 2d3630bb024e2b76e481e2c01ba9c93d7a63efef Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:13:36 -0400 Subject: [PATCH 02/19] Add inline array feature --- standard/conversions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/standard/conversions.md b/standard/conversions.md index 569943084..85d290d11 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -714,6 +714,7 @@ The following implicit conversions are classified as standard implicit conversio - 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. From 7e6d43ee0c52929da4aab571eb4bf8a9e7ec6372 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:20:33 -0400 Subject: [PATCH 03/19] Add inline array feature --- standard/expressions.md | 157 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index f62c68107..5ef33cc1b 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2420,7 +2420,7 @@ The *primary_expression* of an *element_access* shall not be an *array_creation_ 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). @@ -2436,7 +2436,7 @@ In this case the compile-time type of the *element_access* depends on the compil > > *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.11.2](expressions.md#128112-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.11.3](expressions.md#128113-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)); @@ -2444,6 +2444,8 @@ If the *primary_expression* of an *element_access* is: #### 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: @@ -2477,6 +2479,157 @@ The run-time processing of an array access of the form `P[A]`, where `P` is a *p - 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` 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` 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` 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*: +> +> +> ```csharp +> [System.Runtime.CompilerServices.InlineArray(10)] +> public struct Buffer10 +> { +> private T _element0; +> } +> public class Program +> { +> void M1(Buffer10 x) +> { +> ref int a = ref x[0]; // OK +> } +> void M2(in Buffer10 x) +> { +> ref readonly int a = ref x[0]; // OK +> ref int b = ref x[0]; // Error; x is readonly +> } +> Buffer10 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 Slice (int start, int length) +``` + +passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.Span` 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 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 Slice (int start, int length) +``` + +passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.ReadOnlySpan` 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 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*: +> +> +> +> ```csharp +> [System.Runtime.CompilerServices.InlineArray(10)] +> public struct Buffer10 +> { +> private T _element0; +> } +> public class Program +> { +> void M1(Buffer10 x) +> { +> System.Span a = x[..]; // OK +> } +> void M2(in Buffer10 x) +> { +> System.ReadOnlySpan a = x[..]; // OK +> System.Span b = x[..]; // Error; no implicit conversion +> } +> Buffer10 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: From b655b2c2e71204d4cb9a27605603e2660897b54b Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:24:23 -0400 Subject: [PATCH 04/19] Add inline array feature --- standard/structs.md | 89 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/standard/structs.md b/standard/structs.md index e278215d4..b266dc37d 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -477,6 +477,95 @@ constructor declaration. The body of the method assigns each parameter of the De If the instance members accessed in the body do not include a property with a non-`readonly` `get` accessor, then the synthesized `Deconstruct` method is `readonly`. The method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. +## §InlineArray Inline arrays + +A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). + +With some limitations (see later below), an inline array can be used like an array ([§17](arrays.md#17-arrays)). + +Consider the following: + + +```csharp +var buffer = new Buffer(); + +for (int i = 0; i < 5; ++i) +{ + buffer[i] = i; +} + +foreach (var i in buffer) +{ + Console.WriteLine(i); +} + +Console.WriteLine($"buffer[^2] = >{buffer[^2]}<"); +Console.WriteLine($"buffer[1..^0][0] = >{buffer[1..^0][0]}<"); + +[System.Runtime.CompilerServices.InlineArray(5)] +public struct Buffer +{ + private int _element0; + // other, optional, non-instance-field members +} +``` + +which produces this output: + +```console +0 +1 +2 +3 +4 +buffer[^2] = >3< +buffer[1..^0][0] = >1< +``` + +The attribute constructor requires a positive-valued `int` argument that indicates the number of elements in each inline array created from this type, in this case, five. The struct type shall declare exactly one instance field, whose type becomes that of the inline array’s elements. The accessibility of the instance field has no impact on the program’s ability to access the inline array via its struct-instance name, in this case, `buffer`. + +There are a number of restrictions on the instance field’s declaration: + +- It shall not contain the *field_modifier*s `readonly`, `ref`, `required`, or `volatile`. +- It shall not be declared as a *fixed_size_buffer_declaration* ([§24.8](unsafe-code.md#248-fixed-size-buffers)). +- *type* shall be a type valid as a type argument. + +`buffer` is an instance of `Buffer`, and contains an array of five `int` with element `buffer[0]` occupying the same memory as `buffer._element0`. However, unlike an array type, which has a public `Length` property, `buffer` is not derived from `System.Array`, and has no such member. + +> *Note*: One could add a public `Length` property to `Buffer` (which returns `sizeof(Buffer)/sizeof(int)`, but that property would have to be an unsafe member. Alternatively, one could perform an implicit conversion to `System.Span` or `System.ReadOnlySpan` and use their `Length` property. *end note* + +An inline array is a collection; as such, it can be iterated over by a `foreach` statement, as shown. + +The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). + +A list pattern (11.2.x[rcj1.1]) shall not be used in the context of an inline array. + +An inline array type is a valid constructible collection target type for a collection literal. + +Any indexers or `Slice` methods declared for an inline array type that have signatures matching those defined for non-inline array processing, shall not be used during inline array element access. +> *Example*: Consider the following: +> +> +```csharp +> var buffer = new Buffer(); +> int x = buffer[2]; // element access +> +> [System.Runtime.CompilerServices.InlineArray(5)] +> public struct Buffer +> { +> private int _element0; +> public int this[int index] // NOT USED for element access +> { +> get +> { +> … +> } +> } +> } +> ``` +> +> Even though the struct declares an indexer taking an `int` argument, that indexer is not used by element access `buffer[2]`. *end example* + ## 16.5 Record struct and non-record struct differences A record struct differs from a non-record struct in several important ways: From ac1b7a10dc1a7263ea18b1983bd78ea9e5d0c9d7 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:28:11 -0400 Subject: [PATCH 05/19] Add inline array feature --- standard/attributes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/standard/attributes.md b/standard/attributes.md index dbd76ab0e..f4f70a971 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -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)). @@ -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 + +The attribute `InlineArray` 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. From 0fe8c949093c980be5704d2b8aecd9045f81074e Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:32:45 -0400 Subject: [PATCH 06/19] Add inline array feature --- standard/standard-library.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/standard/standard-library.md b/standard/standard-library.md index 0f2dd1bc9..55cc0dee2 100644 --- a/standard/standard-library.md +++ b/standard/standard-library.md @@ -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); @@ -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` From b92ee65f60293a998c32cc39956b65bacf59a60a Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:49:02 -0400 Subject: [PATCH 07/19] fix md formatting --- standard/structs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/structs.md b/standard/structs.md index b266dc37d..fb0e585c1 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -477,7 +477,7 @@ constructor declaration. The body of the method assigns each parameter of the De If the instance members accessed in the body do not include a property with a non-`readonly` `get` accessor, then the synthesized `Deconstruct` method is `readonly`. The method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or is static. -## §InlineArray Inline arrays +## §InlineArray Inline arrays A struct type decorated with the attribute `System.Runtime.CompilerServices.InlineArrayAttribute` (§InlineArrayAttribute) is an ***inline array type***, which is a managed type. An instance of that type is an ***inline array***, a structure that contains a contiguous block of a given number of elements of the same type, and nothing else. It’s the safe-code equivalent of unsafe-code’s fixed-size buffer ([§24.8](unsafe-code.md#248-fixed-size-buffers)). @@ -538,7 +538,7 @@ An inline array is a collection; as such, it can be iterated over by a `foreach` The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). -A list pattern (11.2.x[rcj1.1]) shall not be used in the context of an inline array. +A list pattern ([§11.2.11](patterns.md#11211-list-pattern)) shall not be used in the context of an inline array. An inline array type is a valid constructible collection target type for a collection literal. From 27a1db499d3d4ec495caebf77da188e3774ae0c9 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:52:12 -0400 Subject: [PATCH 08/19] fix md formatting --- standard/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/attributes.md b/standard/attributes.md index f4f70a971..993edffb9 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -1578,7 +1578,7 @@ 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 +### §InlineArrayAttribute The InlineArray attribute The attribute `InlineArray` is used to identify a non-record struct as an inline array type. For further information and examples of its use, see §InlineArray. From d2005799c8e709c4e706fd3dfd0ab1b8d54b0c2e Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 18:53:48 -0400 Subject: [PATCH 09/19] fix md formatting --- standard/conversions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/conversions.md b/standard/conversions.md index 85d290d11..12b2dff19 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -468,7 +468,7 @@ The implicit inline array (§InlineArray) conversions are: - From an expression designating a writable inline array with element type `T` to `System.ReadonlySpan` - From an expression designating a readonly inline array with element type `T` to `System.ReadonlySpan` -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.] +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. ## 10.3 Explicit conversions From fad87a0c480acc0848b2e2076ad5f56571aa5ffc Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 19:03:20 -0400 Subject: [PATCH 10/19] fix md formatting --- standard/expressions.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 5ef33cc1b..d2172f34e 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2525,7 +2525,7 @@ with *argument* as the index, on an instance of `System.ReadOnlySpan` that wa ```csharp static T GetItem(«InlineArrayType» array) -``` +``` > *Example*: > @@ -2567,7 +2567,7 @@ The value of *argument* is converted to `int` and the element access is interpre *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 .] +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`** @@ -2589,15 +2589,15 @@ If *primary_no_array_creation_expression* is a readonly variable, the result of public ReadOnlySpan Slice (int start, int length) ``` -passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.ReadOnlySpan` 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 +passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.ReadOnlySpan` 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 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 .] +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. +If *primary_no_array_creation_expression* is a value, an error is reported. > *Example*: > From 43fc556998591cbef53a3e0b1eb8c37fddb84a9c Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Mon, 6 Apr 2026 19:09:45 -0400 Subject: [PATCH 11/19] fix links --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index d2172f34e..11e2f82df 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2436,7 +2436,7 @@ In this case the compile-time type of the *element_access* depends on the compil > > *end example* -If the *primary_expression* of an *element_access* is a value of an *array_type*, the *element_access* is an array access ([§12.8.11.2](expressions.md#128112-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.11.3](expressions.md#128113-indexer-access)). +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)); From 5a868c5d8c790183abaeb97ee0895ca13003c6ea Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 7 Apr 2026 06:58:51 -0400 Subject: [PATCH 12/19] fix md formatting --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 11e2f82df..f9ea94888 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2507,7 +2507,7 @@ If *primary_no_array_creation_expression* is a readonly variable, the result of public ref readonly T this[int index] { get; } ``` -with *argument* as the index, on an instance of `System.ReadOnlySpan` 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 +with *argument* as the index, on an instance of `System.ReadOnlySpan` 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) From 502e4295e543165af5c21b92b53aa72f503fcf72 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 7 Apr 2026 07:06:27 -0400 Subject: [PATCH 13/19] fix md formatting --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index f9ea94888..3ea1bd64b 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2493,7 +2493,7 @@ If *primary_no_array_creation_expression* is a writable variable, the result of public ref T this[int index] { get; } ``` -with *argument* as the index, on an instance of `System.Span` 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 +with *argument* as the index, on an instance of `System.Span` 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) From 1cecec18273fc7fd2d10413b5c237b0bbbcb209b Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 7 Apr 2026 07:08:23 -0400 Subject: [PATCH 14/19] fix md formatting --- standard/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/expressions.md b/standard/expressions.md index 3ea1bd64b..375eab940 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2577,7 +2577,7 @@ If *primary_no_array_creation_expression* is a writable variable, the result of public Span Slice (int start, int length) ``` -passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.Span` 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 +passing the `int` equivalents of the Range’s start and end Indexes, respectively, on an instance of `System.Span` 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 GetSlice(ref «InlineArrayType» array) From 13e32411926ff06fd772fbb536aae547e238ec24 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Tue, 15 Sep 2026 11:20:47 -0400 Subject: [PATCH 15/19] tweak attribute text --- standard/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/attributes.md b/standard/attributes.md index 993edffb9..f6feb1e40 100644 --- a/standard/attributes.md +++ b/standard/attributes.md @@ -1580,7 +1580,7 @@ This attribute indicates that the current type has one or more required members ### §InlineArrayAttribute The InlineArray attribute -The attribute `InlineArray` is used to identify a non-record struct as an inline array type. For further information and examples of its use, see §InlineArray. +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 From fa24f89d501c1bf61618bd887364e8681288b607 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 21 Sep 2026 17:09:32 -0400 Subject: [PATCH 16/19] Fix inline array links and example metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bce5e82a-89fd-4655-bc08-6d6ba97f0cc6 --- standard/structs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/structs.md b/standard/structs.md index fb0e585c1..dac03f89e 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -538,14 +538,14 @@ An inline array is a collection; as such, it can be iterated over by a `foreach` The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). -A list pattern ([§11.2.11](patterns.md#11211-list-pattern)) shall not be used in the context of an inline array. +A list pattern (§list-pattern-new-clause) shall not be used in the context of an inline array. An inline array type is a valid constructible collection target type for a collection literal. Any indexers or `Slice` methods declared for an inline array type that have signatures matching those defined for non-inline array processing, shall not be used during inline array element access. > *Example*: Consider the following: > -> +> ```csharp > var buffer = new Buffer(); > int x = buffer[2]; // element access From 7c1d356100f7c56275ab04d4d78eedee44388c1c Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 21 Sep 2026 17:22:38 -0400 Subject: [PATCH 17/19] Compile inline array indexer example Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bce5e82a-89fd-4655-bc08-6d6ba97f0cc6 --- standard/structs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/structs.md b/standard/structs.md index dac03f89e..1d1cde898 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -545,7 +545,7 @@ An inline array type is a valid constructible collection target type for a colle Any indexers or `Slice` methods declared for an inline array type that have signatures matching those defined for non-inline array processing, shall not be used during inline array element access. > *Example*: Consider the following: > -> +> ```csharp > var buffer = new Buffer(); > int x = buffer[2]; // element access @@ -558,7 +558,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > { > get > { -> … +> return 0; > } > } > } From 3bd2bd67942b48c39d2dea138a77d78014c80d12 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 21 Sep 2026 20:16:23 -0400 Subject: [PATCH 18/19] Use finalized list pattern cross-reference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bce5e82a-89fd-4655-bc08-6d6ba97f0cc6 --- standard/structs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/structs.md b/standard/structs.md index 1d1cde898..d23558f94 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -538,7 +538,7 @@ An inline array is a collection; as such, it can be iterated over by a `foreach` The elements of the inline array can be accessed for read or write via subscripting (§InlineArrayElementAccess). -A list pattern (§list-pattern-new-clause) shall not be used in the context of an inline array. +A list pattern ([§11.2.11](patterns.md#11211-list-pattern)) shall not be used in the context of an inline array. An inline array type is a valid constructible collection target type for a collection literal. From c66971b0dbb1eed58ff7a29adea6f63b4c885d64 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 22 Sep 2026 11:51:44 -0400 Subject: [PATCH 19/19] Apply suggestion from @BillWagner --- standard/structs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/structs.md b/standard/structs.md index d23558f94..bdb9a69fc 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -546,7 +546,7 @@ Any indexers or `Slice` methods declared for an inline array type that have sign > *Example*: Consider the following: > > -```csharp +> ```csharp > var buffer = new Buffer(); > int x = buffer[2]; // element access >