From 06e6d7e40b9b8923f5dd99e4997c402cfd0b3122 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 19 Mar 2025 15:11:53 -0700 Subject: [PATCH 1/4] Draft grammar to permit nullable types as array element types. --- standard/arrays.md | 7 ++-- standard/types.md | 3 ++ .../Samples/v8/Arrays of nullables/ReadMe.md | 3 ++ .../Arrays of nullables/_Sample_Options.txt | 1 + .../Samples/v8/Arrays of nullables/sample.cs | 36 +++++++++++++++++++ 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/ReadMe.md create mode 100644 tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/_Sample_Options.txt create mode 100644 tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/sample.cs diff --git a/standard/arrays.md b/standard/arrays.md index ccfcfe278..5dccc36eb 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -46,9 +46,10 @@ In effect, the *rank_specifier*s are read from left to right *before* the final > *Example*: The type in `T[][,,][,]` is a single-dimensional array of three-dimensional arrays of two-dimensional arrays of `int`. *end example* -At run-time, a value of an array type can be `null` or a reference to an instance of that array type. - -> *Note*: Following the rules of [§17.6](arrays.md#176-array-covariance), the value may also be a reference to a covariant array type. *end note* +At run-time, a value of an array type can be: +- `null`; or +- a reference to an instance of that array type; or +- a reference to an instance of a covariant array type, following the rules of [§17.6](arrays.md#176-array-covariance). ### 17.2.2 The System.Array type diff --git a/standard/types.md b/standard/types.md index a431c7273..f4de779e8 100644 --- a/standard/types.md +++ b/standard/types.md @@ -64,6 +64,7 @@ non_array_type | delegate_type | 'dynamic' | type_parameter + | nullable_reference_type | pointer_type // unsafe code support ; @@ -738,6 +739,8 @@ There are two forms of nullability for reference types: 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 only exception to this general rule is that adding a nullable annotation can change the syntactic meaning of the type of an array of arrays. Specifically, a type such as `A[][,]` is an array of two-dimensional arrays. That is because the syntactic meaning of the array dimensions in the array type are read from the inside out. However, by adding a nullable annotation between the dimensions, writing `A[]?[,]`, changes the parsing and therefore syntactic meaning of the type. In this case, the element type of the array is `A[]?`. The type is now a two-dimensional array of a nullable array type. + ### 8.9.2 Non-nullable reference types A ***non-nullable reference type*** is a reference type of the form `T`, where `T` is the name of the type. The default null-state of a non-nullable variable is *not-null*. Warnings may be generated when an expression that is *maybe-null* is used where a *not-null* value is required. diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/ReadMe.md b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/ReadMe.md new file mode 100644 index 000000000..d1ef23063 --- /dev/null +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/ReadMe.md @@ -0,0 +1,3 @@ +# Sample: Arrays of NRT + +Samples for nullable arrays, arrays of nullables, and nullable arrays of nullables. diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/_Sample_Options.txt b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/_Sample_Options.txt new file mode 100644 index 000000000..a96c4cd34 --- /dev/null +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/_Sample_Options.txt @@ -0,0 +1 @@ +-ms Rules -rt diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/sample.cs b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/sample.cs new file mode 100644 index 000000000..714f34241 --- /dev/null +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v8/Arrays of nullables/sample.cs @@ -0,0 +1,36 @@ +class ArraysOfNullable +{ + class A { } + + void ArraysOfNullable() + { + A[] p_1 = new A[5]; // Array of non-nullable A all elements inited to null (oops) + A[]? q_1 = null; // Nullable array of non-nullable A, array inited to null + A?[] r_1 = new A[5]; // Array of nullable A all elements inited to null + A?[]? s_1 = null; // Nullable array of nullable A, array inited to null + + string[] p_2 = new string[5]; // Array of non-nullable string all elements inited to null (oops) + string[]? q_2 = null; // Nullable array of non-nullable string, array inited to null + string?[] r_2 = new string[5]; // Array of nullable string all elements inited to null + string?[]? s_2 = null; // Nullable array of nullable string, array inited to null + + int[] p_3 = new int[5]; // Array of non-nullable int all elements inited to 0 + int[]? q_3 = null; // Nullable array of non-nullable int, array inited to null + int?[] r_3 = new int[5]; // Array of nullable int all elements inited to null + int?[]? s_3 = null; // Nullable array of nullable int, array inited to null + + dynamic[] p_4 = new dynamic[5]; // Array of non-nullable dynamic all elements inited to 0 + dynamic[]? q_4 = null; // Nullable array of non-nullable dynamic, array inited to null + dynamic?[] r_4 = new dynamic[5]; // Array of nullable dynamic all elements inited to null + dynamic?[]? s_4 = null; // Nullable array of nullable dynamic, array inited to null + + A[][,] p_5 = new A[1][1,1]; // Array of two-dimensional array + A[][,]? q_5 = null; // Array of two-dimensional array + A[]?[,] r_5 = new A[]?[1,1]; // Two dimensional array of array + A[]?[,]? s_5 = null; // Two dimensional array of array + A?[][,] t_5 = new A[1][1,1]; // Array of two-dimensional array + A?[][,]? u_5 = null; // Array of two-dimensional array + A?[]?[,] v_5 = new A[]?[1,1]; // Two dimensional array of array + A?[]?[,]? w_5 = null; // Two dimensional array of array + } +} From 2037e3fbe497334e2a9cd41508a8005065905f86 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 19 Mar 2025 15:25:40 -0700 Subject: [PATCH 2/4] Fix markdown. --- standard/arrays.md | 1 + 1 file changed, 1 insertion(+) diff --git a/standard/arrays.md b/standard/arrays.md index 5dccc36eb..f9d7d6c1e 100644 --- a/standard/arrays.md +++ b/standard/arrays.md @@ -47,6 +47,7 @@ In effect, the *rank_specifier*s are read from left to right *before* the final > *Example*: The type in `T[][,,][,]` is a single-dimensional array of three-dimensional arrays of two-dimensional arrays of `int`. *end example* At run-time, a value of an array type can be: + - `null`; or - a reference to an instance of that array type; or - a reference to an instance of a covariant array type, following the rules of [§17.6](arrays.md#176-array-covariance). From c5128723c206f313288ef4a2365780f3bcd42606 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 19 Mar 2025 15:38:25 -0700 Subject: [PATCH 3/4] Attempt to remove left recursion. --- standard/types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/types.md b/standard/types.md index f4de779e8..e55bbb1fa 100644 --- a/standard/types.md +++ b/standard/types.md @@ -54,7 +54,8 @@ interface_type ; array_type - : non_array_type rank_specifier+ + | non_array_type rank_specifier+ + | non_array_type ( nullable_type_annotation rank_specifier+ )+ ; non_array_type @@ -64,7 +65,6 @@ non_array_type | delegate_type | 'dynamic' | type_parameter - | nullable_reference_type | pointer_type // unsafe code support ; From 71b95ec9b4d1670d56a4993ccf362bd163cb31f2 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 19 Mar 2025 15:39:51 -0700 Subject: [PATCH 4/4] Fix grammar --- standard/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/types.md b/standard/types.md index e55bbb1fa..869d587b5 100644 --- a/standard/types.md +++ b/standard/types.md @@ -54,7 +54,7 @@ interface_type ; array_type - | non_array_type rank_specifier+ + : non_array_type rank_specifier+ | non_array_type ( nullable_type_annotation rank_specifier+ )+ ;