117 lines
4.2 KiB
Markdown
117 lines
4.2 KiB
Markdown
|
|
||
|
# C# Language Design Notes for Oct 29, 2018
|
||
|
|
||
|
## Agenda
|
||
|
|
||
|
[Source-level opt-in to nullable reference types](https://github.com/dotnet/csharplang/issues/1939)
|
||
|
|
||
|
## 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:
|
||
|
|
||
|
1. Specify all the details in the language spec, including annotations.
|
||
|
2. 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:
|
||
|
|
||
|
```C#
|
||
|
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
|
||
|
|
||
|
```C#
|
||
|
#pragma warning CS4321 restore
|
||
|
```
|
||
|
|
||
|
but it is actually
|
||
|
|
||
|
```C#
|
||
|
#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.
|