4.2 KiB
C# Language Design Notes for Oct 29, 2018
Agenda
Source-level opt-in to nullable reference types
Discussion
Philosophy of specification
To start off we discussed the proposal in the broader context of specifying nullability as a feature in the language specification. The proposal talks about "nullable contexts" but we also need to decide what a "context" implies.
Two basic approaches:
- Specify all the details in the language spec, including annotations.
- Specify very loosely: "'?' means the programmer expects the value may be null. The absence means the programmer does not expect the value to be null."
Where we land on this spectrum decides how prescriptive we need to be about the warnings produced and exactly what conditions produce them.
First question: how much does the spec act as the intermediary of conforming
compiler implementations? One argument is that warnings are not decisions
about legal programs, so the requirements are softer than other areas of the
spec. On the other hand, warnings often make a big difference when trying to
port from one compiler to another, regardless of how much they matter to the
spec. In the past, presence of warnings has been a major factor in porting
from msc
to csc
and vice versa.
However, the Roslyn analyzer public API could be seen as part of the warning surface which is entirely at the compiler level, and creates far more burden on other C# compiler implementations than any spec addition.
An elaboration of (2) is that we could think about the entire feature, aside
from the new syntax for ?
and !
as a "built-in analyzer" for the compiler
that isn't strictly specified by the language, but also therefore cannot
affect the semantics of the language.
Conclusion
We're actually going to end up somewhere in a spectrum between (1) and (2), but we're interested in leaning more towards (2).
Annotation vs Warning context
*Q: Do we want to provide warnings about ?
when the annotation context is
disabled?
Similarly, do we want to emit metadata that treats these as nullable types to users of the library?
If we don't warn, this would allow you to easily add ?
for use in other
areas of the code where the context is enabled, letting you easily annotate
your code over time.
On the other hand, there's no way to go the other direction, indicating that parameters are non-nullable and that nullable types should not be passed.
The original motivation was about a new user using the feature and you annotate one parameter of your method:
void M(string arg1, string? arg2)
Without a pragma setting the non-null context, arg1
is oblivious, but arg2
is nullable. The user may not realize that arg1
is not non-nullable because
they don't have a pragma. The warning is a feedback system to let a user know
that they only part of the nullable feature enabled.
Conclusion
Warn about ?
when annotation context is off. Regardless of the annotation
context, the type is considered nullable and will generate warnings if used
by a consumer in a warning-enabled context. Similarly, metadata will persist
the nullable type and the consumer will consider the type nullable.
Q: Do we warn on !
when the warning context is off?
First item -- even with the proposal, it's not clear what it means for a warning context to be on or off. Does disabling the warning mean that the warning context is off?
Conclusion
Don't warn about !
, regardless of context.
Scenarios
There's some argument that (5) and (6) may be more important/common than (3) and (4), but that doesn't mean the conclusions change.
Conclusions
We like the #nullable ...
directive, but we're not sure about the
#pragma warning nullable ...
. Let's keep it for now, but we're not settled on
a specific definition.
Note: the proposal has the current syntax wrong. The proposal lists the syntax for configuring a diagnostic as
#pragma warning CS4321 restore
but it is actually
#pragma warning restore CS4321
This was not intentional and the proposal should not be read as flipping the
ID order. In the proposal, nullable
is meant to stand in for the diagnostic
identifier, effectively acting as a reserved diagnostic ID.