From 066fbfca335b2c0511f2efd9acfd7a0d96783edf Mon Sep 17 00:00:00 2001 From: jnm2 Date: Wed, 30 Jul 2025 20:07:43 -0400 Subject: [PATCH 1/3] Fix grammar to allow arrays of nullable reference types --- standard/types.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/standard/types.md b/standard/types.md index 31ccd4773..b3fb54f86 100644 --- a/standard/types.md +++ b/standard/types.md @@ -54,16 +54,13 @@ interface_type ; array_type - : non_array_type rank_specifier+ + : array_type nullable_type_annotation rank_specifier+ + | non_array_type rank_specifier+ ; non_array_type : value_type - | class_type - | interface_type - | delegate_type - | 'dynamic' - | type_parameter + | (class_type | interface_type | delegate_type | 'dynamic' | type_parameter) nullable_type_annotation? | pointer_type // unsafe code support ; From aa5e4b5a22ba1792a8191a96660f14562958b136 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Wed, 30 Jul 2025 21:00:41 -0400 Subject: [PATCH 2/3] Document the exception to the rule that nullable annotations can be ignored by compilers --- standard/types.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/standard/types.md b/standard/types.md index b3fb54f86..a405918aa 100644 --- a/standard/types.md +++ b/standard/types.md @@ -729,7 +729,25 @@ There are two forms of nullability for reference types: > *Note:* The types `R` and `R?` are represented by the same underlying type, `R`. A variable of that underlying type can either contain a reference to an object or be the value `null`, which indicates “no reference.” *end note* -The syntactic distinction between a *nullable reference type* and its corresponding *non-nullable reference type* enables a compiler to generate diagnostics. A compiler must allow the *nullable_type_annotation* as defined in [§8.2.1](types.md#821-general). The diagnostics must be limited to warnings. Neither the presence or absence of nullable annotations, nor the state of the nullable context can change the compile time or runtime behavior of a program except for changes in any diagnostic messages generated at compile time. +The syntactic distinction between a *nullable reference type* and its corresponding *non-nullable reference type* enables a compiler to generate diagnostics. A compiler must allow the *nullable_type_annotation* as defined in [§8.2.1](types.md#821-general). The diagnostics must be limited to warnings. Neither the presence or absence of nullable annotations, nor the state of the nullable context can change the compile time or runtime behavior of a program except for changes in any diagnostic messages generated at compile time, with one exception: + +A compiler must respect the effect that *nullable_type_annotation* has on the ordering of array rank specifiers. Whereas `A[][,]` is a single *array_type* with two *rank_specifier*s, the presence of a nullable annotation between the rank specifiers in `A[]?[,]` causes it to no longer be a single *array_type*, but rather two: an outer *array_type* with a single *rank_specifier* of `[,]`, and an element type of `A[]?` which is a *nullable_reference_type* containing an inner *array_type* with a single *rank_specifier* of `[]`. Because of this, `A[]?[,]` and `A[,][]` are represented by the same underlying type, while `A[]?[,]` and `A[][,]` are not. + +> *Example*: The array ranks are interrupted by the '?' in the parameter type, changing the meaning of the underlying array type: +> +> +> ```csharp +> #nullable enable +> class C +> { +> void M(string[][,]?[,,][,,,] arrays) +> { +> string? value = arrays[3, 3, 3][4, 4, 4, 4]?[1][2, 2]; +> } +> } +> ``` +> +> *end example* ### 8.9.2 Non-nullable reference types From 74b51aa3127a61857cd9c6acdb73bda7e3f659c5 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Sat, 9 Aug 2025 16:11:14 -0400 Subject: [PATCH 3/3] Add new rule to avoid parenthesized grammar --- standard/types.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/standard/types.md b/standard/types.md index a405918aa..ec8954413 100644 --- a/standard/types.md +++ b/standard/types.md @@ -59,11 +59,19 @@ array_type ; non_array_type - : value_type - | (class_type | interface_type | delegate_type | 'dynamic' | type_parameter) nullable_type_annotation? + : non_array_non_nullable_type nullable_type_annotation? | pointer_type // unsafe code support ; +non_array_non_nullable_type + : non_nullable_value_type + | class_type + | interface_type + | delegate_type + | 'dynamic' + | type_parameter + ; + rank_specifier : '[' ','* ']' ;