Skip to content

Fix small spec bugs regarding nullable reference type parameters #1389

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

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

Conversation

jnm2
Copy link
Contributor

@jnm2 jnm2 commented Aug 9, 2025

While working on #1386, I found some spec bugs I could fix.

@jnm2 jnm2 force-pushed the jnm2/nrt_type_params branch from 62bd6f5 to a4af924 Compare August 9, 2025 20:38
@@ -27,7 +27,7 @@ For convenience, throughout this specification, some library type names are writ

### 8.2.1 General

A reference type is a class type, an interface type, an array type, a delegate type, or the `dynamic` type. For each non-nullable reference type, there is a corresponding nullable reference type noted by appending the `?` to the type name.
A reference type is a class type, an interface type, an array type, a delegate type, the `dynamic` type, or any type parameter that is constrained to be a reference type (that is, any type parameter with the reference type constraint or a class type constraint ([§15.2.5](classes.md#1525-type-parameter-constraints))). For each non-nullable reference type, there is a corresponding nullable reference type noted by appending the `?` to the type name.
Copy link
Contributor Author

@jnm2 jnm2 Aug 9, 2025

Choose a reason for hiding this comment

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

This borrows the existing language which appears in https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/types.md#8312-nullable-value-types:

Conversely, a non-nullable value type is any value type other than System.Nullable<T> and its shorthand T? (for any T), plus any type parameter that is constrained to be a non-nullable value type (that is, any type parameter with a value type constraint (§15.2.5)).

@@ -443,7 +443,7 @@ The nullability of the type argument need not match the nullability of the type
> *Note*: To specify that a type argument is a nullable reference type, don’t add the nullable type annotation as a constraint (use `T : class` or `T : BaseClass`), but use `T?` throughout the generic declaration to indicate the corresponding nullable reference type for the type argument. *end note*

<!-- Remove in C# 9, when this is allowed -->
The nullable type annotation, `?`, can’t be used on an unconstrained type argument.
Copy link
Contributor Author

@jnm2 jnm2 Aug 9, 2025

Choose a reason for hiding this comment

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

Here is an example of a type parameter that is not unconstrained, and thus was not disallowed by the original statement, which is still not allowed to use ?:

#nullable enable

class C
{
    void M<T>(T? test) where T : System.IDisposable
    {
    }
}

Roslyn:

A nullable type parameter must be known to be a value type or non-nullable reference type unless language version '9.0' or greater is used. Consider changing the language version or adding a 'class', 'struct', or type constraint.

@jnm2 jnm2 force-pushed the jnm2/nrt_type_params branch from a4af924 to 2b23085 Compare August 9, 2025 20:44
Comment on lines +448 to +449
<!-- Add in C# 9, when `?` is allowed on nullable reference type parameters. -->
<!-- For a type parameter `T` when the type argument is a nullable reference type `C?`, instances of `T?` are interpreted as `C?`, not `C??`. -->
Copy link
Contributor Author

@jnm2 jnm2 Aug 9, 2025

Choose a reason for hiding this comment

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

Instances of T? do not exist when the type argument is a nullable reference type C? in C# 8, e.g.:

#nullable enable

class C
{
    void M<T>(T? test) where T : class?
    {
    }
}

Roslyn:

A nullable type parameter must be known to be a value type or non-nullable reference type unless language version '9.0' or greater is used. Consider changing the language version or adding a 'class', 'struct', or type constraint.

@jnm2 jnm2 force-pushed the jnm2/nrt_type_params branch from fa3774f to 918e022 Compare August 9, 2025 20:55
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.

1 participant