
# C# Language Design Meeting for Nov. 13th, 2019

## Agenda

1. Discriminated unions
2. Improved analysis of `[MaybeNull]T`

## Discussion

### Initial discriminated union proposal

https://github.com/dotnet/csharplang/blob/master/proposals/discriminated-unions.md

Questions around some restrictions:

1. Why can't you have constructor parameters on the enum class type?
    - No real reason, except worries about inheritance aside from members
        - Keeping inheritance syntactically close by is considered a feature of the proposal,
          since the user can easy analyze what all the possible children of the root are
    - Syntax for the base call in value members would have to be specified

2. How `partial` do we want to allow things? There's good reason to put all the members together

3. Are records short enough syntax that we don't need the "simple" type syntax?

    - Regardless of brevity, if members are required to explicitly inherit from the root this seems
      like purely useless work, since doing otherwise would be an error

4. What if you want to define just regular nested classes, that don't inherit from the root type?

5. Scoping for nested enum class members? The proposal for altering binding wouldn't help with
   nested members, because it only applies to simple names.

```C#
enum class Expr
{
    enum class BinaryOperator
    {
        Add(Expr left, Expr right),
        Multiply(Expr left, Expr right)
    }
}

Expr M(Expr left, Expr right)
{
    return Add(left, right); // error, no name "Add" found under Expr
}

int M(Expr e) => e switch
{
    Add _ => 0, // error, no name Add found under Expr
}
```

There's also a proposed alternate syntax that would let you put everything directly into the enum
class:

```C#
enum class Color
{
    Red,
    Greed; // semicolon delimiting end of enum class cases, and start of regular members

    public static int HelperField;
    public static int HelperProperty => 0;
    public int HelperMethod() => 0;
}
```


## Improved analysis of `[MaybeNull]T`

Proposal: https://github.com/dotnet/csharplang/issues/2946

The new proposed abstract domain for nullable analysis would be:

```C#
enum
{
    NotNull,
    MaybeNull,
    MaybeNullEvenIfNotNullable
}
```


If we improve analysis of `MaybeNull` inside the method, do we want to push the new functionality
through for all the nullable attributes at the same time? This seems useful from a consumer
perspective, in that you get the different warnings all at the same time, but there's also the
simple question of resources and scheduling.

Similarly, if we do improve `MaybeNull` analysis in the body of the method, do we need to improve
the analysis in other places, like overriding, at the same time? Or are we OK with a piecemeal state
where `MaybeNull` is enforced in the method body but not in overriding? Or where we enforce `MaybeNull`
in overriding, but not other attributes like `DisallowNull`?

A broader question is how common `MaybeNull` is in general. Our experience in the .NET Core mscorlib
is that there are only 10 occurrences of `MaybeNull`, and even when broadening to LINQ, there are at
most a few dozen occurrences, mostly in places that may return a `default` value. In comparison,
`NotNullIfNotNull` has ~30 occurrences in mscorlib.

On the other hand, `default(T)` is very common and is an instance of `MaybeNull` in a sense. This implies
that the flow state of `MaybeNull` is particularly important.

An additional question is whether or not to revive the `T?` proposal to deal with the historical problems
around `MaybeNull` annotations on locals and other places where attributes are not permitted.

**Conclusion**

We think improving any aspect of the attributes can be considered independently and we will not
require the changes to ship together. We think that proposal is good. Accepted.

No statement on `T?`. We will schedule a discussion soon to get a permanent decision on the proposal.
