-
Notifications
You must be signed in to change notification settings - Fork 93
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
base: draft-v8
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,7 +395,7 @@ | |
: 'where' type_parameter ':' type_parameter_constraints | ||
; | ||
|
||
type_parameter_constraints | ||
: primary_constraint (',' secondary_constraints)? (',' constructor_constraint)? | ||
| secondary_constraints (',' constructor_constraint)? | ||
| constructor_constraint | ||
|
@@ -442,10 +442,11 @@ | |
|
||
> *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. | ||
<!-- Remove in C# 9, when `?` is allowed on any type parameter. --> | ||
The nullable type annotation, `?`, can only be used on a type parameter that has the value type constraint, the reference type constraint without the *nullable_type_annotation*, or a class type constraint without the *nullable_type_annotation*. | ||
|
||
For a type parameter `T` when the type argument is a nullable reference type `C?`, instances of `T?` are interpreted as `C?`, not `C??`. | ||
<!-- 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??`. --> | ||
Comment on lines
+448
to
+449
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instances of #nullable enable
class C
{
void M<T>(T? test) where T : class?
{
}
} Roslyn:
|
||
|
||
> *Example*: The following examples show how the nullability of a type argument impacts the nullability of a declaration of its type parameter: | ||
> | ||
|
@@ -503,15 +504,15 @@ | |
> static void M() | ||
> { | ||
> // nonnull constraint allows nonnullable struct type argument | ||
> A<int> x1; | ||
> // possible warning: nonnull constraint prohibits nullable struct type argument | ||
> A<int?> x2; | ||
> // nonnull constraint allows nonnullable class type argument | ||
> A<C> x3; | ||
> // possible warning: nonnull constraint prohibits nullable class type argument | ||
> A<C?> x4; | ||
> // nonnullable base class requirement allows nonnullable class type argument | ||
> B1<C> x5; | ||
> // possible warning: nonnullable base class requirement prohibits nullable class type argument | ||
> B1<C?> x6; | ||
> // nullable base class requirement allows nonnullable class type argument | ||
|
@@ -3455,7 +3456,7 @@ | |
> static void Main() | ||
> { | ||
> field = 10; | ||
> Console.WriteLine(Property); // Prints 10 | ||
> Property = 20; // This invokes the get accessor, then assigns | ||
> // via the resulting variable reference | ||
> Console.WriteLine(field); // Prints 20 | ||
|
@@ -4570,7 +4571,7 @@ | |
: '!' | ||
; | ||
|
||
overloadable_unary_operator | ||
: '+' | '-' | logical_negation_operator | '~' | '++' | '--' | 'true' | 'false' | ||
; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,7 @@ | |
|
||
### 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. | ||
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
|
||
|
||
```ANTLR | ||
reference_type | ||
|
@@ -946,13 +946,13 @@ | |
> public void M(string s) | ||
> { | ||
> int length = s.Length; // No warning. s is not null | ||
> | ||
> _ = s == null; // Null check by testing equality. The null state of s is maybe null | ||
> length = s.Length; // Warning, and changes the null state of s to not null | ||
> | ||
> _ = s?.Length; // The ?. is a null check and changes the null state of s to maybe null | ||
> if (s.Length > 4) // Warning. Changes null state of s to not null | ||
> { | ||
> _ = s?[4]; // ?[] is a null check and changes the null state of s to maybe null | ||
> _ = s.Length; // Warning. s is maybe null | ||
> } | ||
|
@@ -1012,7 +1012,7 @@ | |
> { | ||
> var t = new Test(); | ||
> if (t.DisappearingProperty != null) | ||
> { | ||
> int len = t.DisappearingProperty.Length; // No warning. A compiler can assume property is stateful | ||
> } | ||
> } | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
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
?
:Roslyn: