Skip to content

Allow arrays of nullable reference types #1386

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: draft-v8
Choose a base branch
from
Draft

Conversation

jnm2
Copy link
Contributor

@jnm2 jnm2 commented Jul 31, 2025

Proposed replacement for @Nigel-Ecma's #1287 and @gafter's #1297

Will fix #1385

I was trying not to end up creating new names like non_array_non_nullable_reference_type and non_array_nullable_reference_type which don't sound like core concepts we'd want to be referencing elsewhere. (Cf #1287)

TODO:

  • Add samples for the grammer tester. (Getting help from @Nigel-Ecma offline. I would like to create tests that show that string?[] and int[]?[] were disallowed prior to the grammar changes in this PR.)

Comment on lines 56 to +58
array_type
: non_array_type rank_specifier+
: array_type nullable_type_annotation rank_specifier+
| non_array_type rank_specifier+
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This has the property that when parsing string?[][,]?[,,][,,,]? we end up with two array_type nodes: one being string?[][,]?[,,][,,,], and one being the inner string?[][,].

@Nigel-Ecma It's not mutual left recursion! 😁

| delegate_type
| 'dynamic'
| type_parameter
| (class_type | interface_type | delegate_type | 'dynamic' | type_parameter) nullable_type_annotation?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This fixes the issue where string?[] and other arrays of reference-typed non-arrays were disallowed by the grammar.

@jnm2 jnm2 force-pushed the jnm2/arrays_of_nrt branch from 8b0a578 to aa5e4b5 Compare July 31, 2025 01:29
Copy link
Contributor

@Nigel-Ecma Nigel-Ecma left a comment

Choose a reason for hiding this comment

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

Nothing wrong with being concise; however unfortunately some of the conciseness is in the wrong places, and there are concerns this isn’t complete coverage of the feature.

Comment on lines +57 to +58
: array_type nullable_type_annotation rank_specifier+
| non_array_type rank_specifier+
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, no MLR, well done ;-)

This change impacts §17.2 which now needs to be revised.

Comment on lines +732 to +734
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.
Copy link
Contributor

Choose a reason for hiding this comment

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

  • This is not the place to define the semantics of array types, that is §17.2
  • The final sentence doesn’t cover the consequences of having the same underlying, which presumably exist or the statement is pointless. Are there implications for array creation and conversions which will need to addressed in the respective clauses?
  • There are “tonal” issues here:
    • A implementation must support the syntax and semantics of the language – rather and “respect the effect of”
    • A token has no power per se, the grammar states where a token is allowed and the semantics specifies the meaning of the grammar's phrases/sentences – rather then “the presence of a … causes”
  • What does need to go here is a simple statement that nullable annotations can effect the semantics with a cross reference to where that effect is defined (probably just somewhere in §17 at present, but the future may bring others now the “no effect” status has gone)
    • This change impacts at least one other place in the Standard – see Nullability: conversion behavior #1242 – but there may be more…
    • I am assuming here that you do not intend to use the “conditionally normative” device to maintain the no effect status in the bulk of the Standard. If you do this last point & sub-point need to be considered in that light.

Comment on lines +735 to +750

> *Example*: The array ranks are interrupted by the '?' in the parameter type, changing the meaning of the underlying array type:
>
> <!-- Example: {template:"code-in-class-lib", name:"ArraysOfNullAbleArrays"} -->
> ```csharp
> #nullable enable
> class C
> {
> void M(string[][,]?[,,][,,,] arrays)
> {
> string? value = arrays[3, 3, 3][4, 4, 4, 4]?[1][2, 2];
> }
> }
> ```
>
> *end example*
Copy link
Contributor

Choose a reason for hiding this comment

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

As with the above this needs to be in §17 somewhere. Giving examples of how adding nullable annotations to examples already in §17 could help the understanding, e.g. In §17.2.1 there is:

Example: The type in T[][,,][,] is a single-dimensional array of three-dimensional arrays of two-dimensional arrays of int. end example

In these terms what is T[]?[,,][,], T[]?[,,][,] and maybe even T[]?[,,]?[,]?

An example demonstrating the differences, in the same terms as above, between T[][,][,,][,,,][,,,,][,,,,,] and T[][,]?[,,][,,,]?[,,,,][,,,,,] might be helpful (multiple annotations, multiple ranks between & around them)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Arrays of nullable references
2 participants