dotnet / csharplang

The official repo for the design of the C# programming language
11.55k stars 1.03k forks source link

Limit scope of nullable annotation '?' to references only, excluding "type" scenarios #1687

Closed gulshan closed 5 years ago

gulshan commented 6 years ago

Background

"Nullable reference types" is probably the biggest feature of upcoming C# 8. There were lots of discussions regarding the implementation of nullable reference types in last few years. There were discussion in github and obviously in LDMs. Now it has been almost fleshed out and there is already already a working preview. So, it is already late to talk about this feature. But still I want to raise this issue. The main proposal can be found here. Of the LDMs discussing this features, I think the most influential was the one with Anders on Nov 04, 2017. The meeting notes can be found here. And some of the provision decisions of that meeting were confirmed in the next LDM. Some key characteristics of this feature from those documents are (emphasis mine)-

So, it's clear that there are no new types being introduced. These are the same old nullable reference types. Which is evident from typeof and default operations. But now there would be nullability annotation ?, which can be placed with the type like MyClass?. The annotation would be translated into attributes in metadata and provide code fixes around null checking. This does not guarantee anything. So why using "Nullable reference types"? I think because nullability was introduced for value types, it was through a new type Nullable<T>. This feature being similar to that feature but for reference types, shares the word "type" in the name. And this is causing some confusions IMHO.

Proposal

I have raised my concern regarding this naming in the main discussion issue #36 . But it was mainly about omitting the word "type" from the name of the proposal, nothing more than that. And it did not get much traction. But now I am proposing something a bit detail, which is not mere omission of the word "type". The proposal is to only allow nullability annotations on reference declarations/descriptions and prohibit its use with types on other places. This means nullable annotation ? will be-

Allowed on

Not allowed on

The cases I am proposing to not allow nullability annotation, the end result in practice are almost same whether ? is used with type or not. Not allowing ? will reduce the confusion around it, IMHO. This proposal actually limits the use of nullability annotation. But I think it still goes with the decisions made and the overall philosophy of the feature. And I think the name of the feature should be something that conveys the intent and the limits of the feature clearly. Now, I am proposing the name- "Nullable annotations for reference types".

An alternative to directly accepting this proposal is to (just discard the naming suggestion and) count this proposal as a first phase of the current original proposal. At first enable this limited subset of the feature. Then if it is really useful to add nullability annotation everywhere where there is a reference type, that can be discussed/implemented/tried/shipped later separately.

svick commented 6 years ago

First, "nullable references" sounds as if you were allowing null for ref parameters. (Not just a reference to null, but a reference that is itself null.) This means the proposed name is still confusing.

Second, types in C# already aren't the same thing as System.Type. Some examples: object and dynamic are different types in C#, but their Type is System.Object in both cases. Or named tuples, where (int, int), (int a, int b) and (int x, int y) are all considered different types, while for all of them the Type is System.ValueTuple<int, int>. So I don't see expanding that for nullable reference types as an issue.

gulshan commented 6 years ago

A comment at last. So, thanks @svick . But I'm sorry to say, what "nullable references" sounded to you feels totally subjective to me. But whatever it sounds to anyone, s/he cannot start using the feature only from the very first idea that came into mind, S/he has to learn what it really means. Then the meaning becomes clear. And I put the "nullable references" in contrast to "nullable reference types". And then I quoted the main proposal and LDM descriptions trying to show why the former is a better description of the feature.

Regarding types being different in .net and C#, I put specific scenarios where I think nullable annotation ? should not be allowed. In casting, typeof operation, default value operation, constructors and method overloading, adding ? with types currently does the exact same thing it would do without ?. So, not allowing ? reduces confusion. Regarding type parameters and type constraints, allowing ? brings up confusing things like T??. Not allowing nullable annotation in these places reduces the confusion, as I have tried to explain. I think it is not comparable with special dynamic or named tuple types in C#.

CyrusNajmabadi commented 6 years ago

I agree with @svick . Nothing about 'nullable references' seems like a better name than 'nullable reference types'.

And i think 'nullable reference types' very cleanly and simply conveys waht it is. It's a way to say, when using a reference type, if you expect that it can be nullable or not. So 'nullable reference type' seems fairly clear and easy to understand.

HaloFour commented 6 years ago

I don't think that it's so cut and dry with "non-nullable references" (and I have also taken to omitting the "types" from the title). The reason being that unlike other "types" in the C# language a variable can shift back and forth depending on flow analysis. That's not true with dynamic or tuples where, once declared, a variable is always that type. A variable of string? is a string that is potentially null, right up until the point where you've proven that it's not, and then the compiler will consider the type to be string.

I don't think it's necessarily worth arguing over the language or specific aspects of the proposal, but it is worth acknowledging the grey area that this feature introduces that is slightly unlike any of the other special types in C#.

svick commented 6 years ago

In casting, typeof operation, default value operation, constructors and method overloading, adding ? with types currently does the exact same thing it would do without ?.

I think it makes sense to discuss that, but I don't see how is that related to renaming the feature. You have two unrelated proposals, and I think putting them together makes discussing both of them harder.

As for those specific sub-proposals, for example, regarding generics, I think the distinction between e.g. List<string> and List<string?> is very important to have, even if removing would "reduce confusion".

As another example, typeof currently behaves in an interesting way:

So the situation is already not as simple as "typeof(T) works if and only if T is a type". Not sure what that means for e.g. typeof(string?).

On the other hand, I find that new C?() being allowed is weird, especially since it doesn't actually produce a nullable value.

But you're conflating all of those cases together with almost no explanation for why any of them should not be allowed. I think that's another reason why nobody is discussing that part of your proposal until now: there isn't really anything to discuss.

gulshan commented 6 years ago

One thing I should mention. I think limiting the scope of nullability annotation as proposed here is more important than renaming the feature. I apologize, because most probably from this proposal it seemed the opposite- renaming was more emphasized than limiting the feature.

gulshan commented 6 years ago

Updated the title and description. Tried to deemphasized the feature title part. Also proposed a new title for the feature- "Nullability annotations for reference types".

AustinBryan commented 6 years ago

@gulshan Honestly, I thought "Limit scope of nullable annotation ? to references only excluding "type" scenarios" meant have nullibility be only for reference types and not for value types, meaning int? x; would no longer be valid C#.