Add meeting notes for 2019-02-13
This commit is contained in:
parent
4e3f2e4ea5
commit
92d6ef6cc3
178
meetings/2019/LDM-2019-02-13.md
Normal file
178
meetings/2019/LDM-2019-02-13.md
Normal file
|
@ -0,0 +1,178 @@
|
|||
# C# Language Design for February 13th, 2019
|
||||
|
||||
## Agenda
|
||||
|
||||
Nullable Reference Types: Open LDM Issues https://github.com/dotnet/csharplang/issues/2201
|
||||
|
||||
## Discussion
|
||||
|
||||
### Track assignments through `ref` with conditional expressions
|
||||
|
||||
What is the nullability of `ref` variables when assigned through conditional expressions?
|
||||
|
||||
```cs
|
||||
string? x = "";
|
||||
string? y = "";
|
||||
(b ? ref x : ref y) = null;
|
||||
x.ToString(); // warning?
|
||||
y.ToString(); // warning?
|
||||
```
|
||||
|
||||
```cs
|
||||
string? x = null;
|
||||
string? y = null;
|
||||
(b ? ref x : ref y) = "";
|
||||
```
|
||||
|
||||
One option is to assume nullability after a `ref` has been taken to a variable. However,
|
||||
that would mean that a `ref` variable declared non-nullable could become nullable, which
|
||||
seems too heavy-handed.
|
||||
|
||||
Similarly, disabling flow analysis for variables which are taken as the target of a `ref`
|
||||
feels like violating our model, which is largely based on flow analysis.
|
||||
|
||||
Alias analysis, on the other hand, seems to complicated and any reliable implementation
|
||||
would be too difficult for users to understand.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
Let's reach a middle ground. Assignment between any two identifiers copies
|
||||
the state and is then tracked separately. This is also true for `ref` locals.
|
||||
So,
|
||||
|
||||
```C#
|
||||
string? x = "";
|
||||
string? y = "";
|
||||
(b ? ref x : ref y) = null;
|
||||
x.ToString(); // warning
|
||||
y.ToString(); // warning
|
||||
```
|
||||
|
||||
But the equivalent using `ref` locals does not.
|
||||
|
||||
```C#
|
||||
string? x = "";
|
||||
string? y = "";
|
||||
if (b)
|
||||
{
|
||||
ref string? rx = ref x;
|
||||
rx = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref string? ry = ref y;
|
||||
ry = null;
|
||||
}
|
||||
x.ToString(); // no warning
|
||||
y.ToString(); // no warning
|
||||
```
|
||||
|
||||
### Nullability of conditional access with unconstrained type parameters
|
||||
|
||||
What is the nullability of `x?.F()`?
|
||||
|
||||
```cs
|
||||
class C<T, U>
|
||||
where T : U
|
||||
where U : C<T, U>?
|
||||
{
|
||||
static void M(U x)
|
||||
{
|
||||
U y = x?.F();
|
||||
T z = x?.F();
|
||||
}
|
||||
T F() => throw null;
|
||||
}
|
||||
```
|
||||
|
||||
This question seems interesting even without the type parameters and also
|
||||
contains a nested question about reachability.
|
||||
|
||||
Is the `null` case of `?.` reachable even if the expression is non-nullable?
|
||||
And if it is, what is the null state of the LHS?
|
||||
|
||||
```C#
|
||||
string x = "";
|
||||
x?.ToString(); // warning?
|
||||
```
|
||||
|
||||
**Conclusion**
|
||||
|
||||
The `null` case of `?.` is always reachable, meaning the result is always
|
||||
maybe null e.g.,
|
||||
|
||||
```C#
|
||||
var y = x?.M(); // y is maybe null here, if possible
|
||||
```
|
||||
|
||||
Moreover, the LHS is considered maybe null in the null branch, so by normal
|
||||
flow analysis, after the expression is evaluated a variable on the LHS will
|
||||
be considered maybe null.
|
||||
|
||||
```C#
|
||||
string x = "";
|
||||
x?.ToString(); // warning that x is maybe null
|
||||
```
|
||||
|
||||
### `!` operator on L-values
|
||||
|
||||
Where is `!` allowed?
|
||||
|
||||
* `M(out x!);` (note this also definitely assigns to `x` through the `!`)
|
||||
|
||||
* `M(out (x!));`
|
||||
|
||||
* `M(out (RefReturning()!));`
|
||||
|
||||
* `x! = y;`
|
||||
|
||||
* `M(out string x!);`
|
||||
|
||||
Current implementation is to allow in `out` scenarios, but disallow in assignment scenarios.
|
||||
|
||||
We dislike allowing it in regular assignment. We like allowing it in simple
|
||||
`out` parameters. We're ambivalent on `M(out string x!)`, but it's
|
||||
not easily representable in the syntax model and is very similar to the
|
||||
related feature `parameter!`, with the opposite meaning.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
Only allow `!` in simple `out` parameters with no declaration.
|
||||
|
||||
### `is` nullability in `false` case
|
||||
|
||||
See [dotnet/roslyn#30297](https://github.com/dotnet/roslyn/issues/30297)
|
||||
|
||||
```cs
|
||||
string? s = null;
|
||||
if (!(s is object)) { s.ToString(); /* could warn? */ }
|
||||
if (!(s is string)) { s.ToString(); /* could warn? */ }
|
||||
```
|
||||
|
||||
There are variants of this scenario with `string!` and `string~`. Should `is`
|
||||
update the nullability in both branches or should the one branch be treated
|
||||
as unreachable?
|
||||
|
||||
The problematic code is probably more like:
|
||||
|
||||
```C#
|
||||
void M(string s)
|
||||
{
|
||||
if (s is IComparable t)
|
||||
{
|
||||
}
|
||||
s.ToString(); // warning
|
||||
}
|
||||
```
|
||||
|
||||
Here the user may not have meant to do a null check, but gets the
|
||||
side-effects of doing so anyway.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
It seems important to respect a deliberate null check from the
|
||||
user, even if the input variable is non-nullable. As a next step we
|
||||
need to define exactly which tests we think are "deliberate" null
|
||||
checks. For instance, `x is null` is certainly a null check, but
|
||||
pattern matching may or may not be a *deliberate* null check, even
|
||||
if the code contains a null check.
|
|
@ -36,14 +36,16 @@
|
|||
|
||||
- Nullable Reference Types: Open LDM Issues https://github.com/dotnet/csharplang/issues/2201
|
||||
|
||||
## Feb 13, 2019
|
||||
|
||||
Nullable Reference Types: Open LDM Issues https://github.com/dotnet/csharplang/issues/2201
|
||||
|
||||
# C# Language Design Notes for 2019
|
||||
|
||||
Overview of meetings and agendas for 2019
|
||||
|
||||
## Feb 13, 2019
|
||||
|
||||
[C# Language Design Notes for Feb 13, 2019](LDM-2019-02-13.md)
|
||||
|
||||
- Nullable Reference Types: Open LDM Issues https://github.com/dotnet/csharplang/issues/2201
|
||||
|
||||
## Jan 23, 2019
|
||||
|
||||
[C# Language Design Notes for Jan 23, 2019](LDM-2019-01-23.md)
|
||||
|
|
Loading…
Reference in a new issue