csharplang/meetings/2020/LDM-2020-01-06.md

129 lines
4 KiB
Markdown
Raw Normal View History

2020-01-06 20:12:29 +01:00
# C# Language Design Meeting for Jan. 6, 2020
## Agenda
1. Use attribute info inside method bodies
1. Making Task-like types covariant for nullability
1. Casting to non-nullable reference type
1. Triage
## Discussion
### Use attribute info inside method bodies
Examples:
1.
```C#
bool TryGetValue<T>([MaybeNullWhen(false)]out T t)
2020-01-06 20:12:29 +01:00
{
return other.TryGetValue(out t); // currently warns
}
```
2.
```C#
[return: MaybeNull]
T GetFirstOrDefault<T>()
{
return null; // currently warns
}
```
3.
Overriding/implementation
```C#
class A<T>
{
[return: MaybeNull]
virtual T M();
}
class B : A<string>
{
override string? M(); // warns about no [MaybeNull]
}
```
We don't have a complete design here, but some cases have an intuition about the correct
behavior. In overriding, specifically, we need a specification for what it means for an
annotation to be "compatible" with each of the attributes. On the other hand, it's not clear what
the behavior of `MaybeNullWhenTrue` should be in all cases.
**Conclusion**
We'd like to do this if the return on investment seems worth it, but to fully evaluate
we need a proposal of the work.
### Making Task-like objects nullable covariant
This is a pretty common pain-point, and it's not the first time we special-cased variance,
specifically `IEquatable<T>` is treated as nullable contravariant. It's unfortunate that the CLR
doesn't have capability to make `Task<T>` full covariant, but handling even nullable alone would
be useful. Moreover, if we later get the capability to mark `Task<T>` covariant, this would not
harm the effort.
We also think that there may be some special cases introduced for overload resolution where we
consider `Task<T>` as covariant already. If we could reuse that knowledge, that would be useful.
**Conclusion**
Let's see if we can dig up the overload resolution changes for Task-like types and try to adapt
the same rule for making Task-like types nullable covariant.
### Casting to non-nullable reference type
Example:
```C#
BoundNode? node = ...;
if (node.Kind == BoundKind.Expression)
{
var x = (BoundExpression)node; // warning if node is nullable
}
```
The question is if this warning is valuable, or annoying. We've hit this most often in Roslyn
when using the pattern `(object)x == null` to do a null check while avoiding the user-defined
equality check. This is annoying in the Roslyn codebase, but not very common outside it. On the
other hand, there's feeling that when doing the BoundNode to BoundExpression check, which is less
common in Roslyn but more common generally, there's agreement that the warning is useful in
making the type annotated with the most accurate representation of the null state.
**Conclusion**
Keep the warning, no change. We think the warning is valuable for the non-null-check cases. Newer
version of C# have features that address the null check problem and Roslyn should move to use `x
is null` or similar.
## Triage
Three related proposals: #3037, #3038, #377.
These all deal with the general problem of statements in expressions, especially statements in
switch expressions, and switch expression form in statements.
They don't necessarily require each other, but they fit a lot of the same syntax and semantic
space, so we should consider them all together.
There's also a sketch for how we could unify the syntax forms of all of three proposals, with
potential syntax changes.
**Conclusion**
We agree that all of these proposals are addressing important scenarios, and some improvement
here is valuable. We're not sure where we want to go with generalized statements-in-expressions
vs. adding special syntax forms for switch expression/statement.
We're mainly concerned that if we do switch expression blocks, we want to make sure that the we
don't block a future generalization to all expressions. We need to find a generalization that we
like, reject a generalization and accept this syntax, or put these improvements on the
back-burner if we think that a generalization is possible, we just haven't found it.
Accepted for C# 9.0 investigation.