# C# Language Design Meeting for November 10th, 2021

## Agenda

1. [Self types](#self-types)

## Quote of the Day

- "Is that a threat [redacted]?" "I think it's a promise" "Well, then someone gets to tell management why it slipped." "Now that was a threat."

## Discussion

### Self types

https://github.com/dotnet/csharplang/issues/5413

Today, we took a first look at adding a self type constraint to C#, as part of the work on generic math in C#. We see 3 main problems that the self type
constraint could address:

1. Today, generic math using the Curiously Recurring Type Pattern (CRTP) to specify self types, which looks like `interface INumber<T> where T : INumber<T>`.
This is quite verbose, requiring stating the name of the interface twice, and even a small reduction to `interface INumber<T> where T : this` helps both
with the number of characters typed and the clarity of the intent of the code.
2. CRTP does not actually enforce that the `T` implemented must be the current type. For example, someone could do `struct MyStruct : IAdditiveIdentity<int>`,
because `int` implements `IAdditiveIdentity<int>`. CRTP involving operators will naturally enforce that `T` is actually the current type, because of the rules
around operator implementation, but this is complex from both a spec perspective and an implementation perspective.
3. Being able to call explicit implementations of an interface. In .NET 6, many of the preview interface definitions are implemented on types _explicitly_, to
avoid users accidentally taking a dependency on them without meaning to. However, this leads to confusion with how to call that implementation: you have to
create a generic wrapper method, which we've received feedback is quite confusing. While some of these explicit implementations will be transitioned to regular
implementations in .NET 7 when the feature ships for real, a few must remain explicit to avoid covering existing functionality that behaves in a slightly
different manner.

Of these concerns, we think the best motivation for self types is actually the first one. For concern 2, we're unsure what the real harm is. Yes, users can
provide an odd implementation of one of these interfaces, but that's going to be true forever in C# regardless of our decision here, unless we take a breaking
change to `IEquatable<T>` and similar interfaces that shipped with C# 2. It does simplify some rules for the compiler, but ultimately we're not sure that
addressing concern 2 is a motivating factor.

Concern 3 is valid, but we're not sure the self type is the appropriate way to fix it. We've had `base` calls for DIMs on the backlog for a few years now, and
we see the possibility for a more generalized way to call a specific implementation of a method on a type. The current design for the self type happens to
address this concern, but not in a generalized fashion. In addition, several members of the LDM are not convinced by the prevalence of the need to call these
implementations once .NET 7 is out: they do exist, but how common will needing those implementations be?

We also talked about the possibility of using associated types to represent the self type, rather than a public type parameter. While this is somewhat attractive,
we're in general agreement that unless we have real runtime support for an associated self type, we don't want to take this direction. In C#, we generally avoid
having metadata significantly differ from the source; if the metadata needs to have a generic type parameter, then we would like the source to indicate such.
At some point, associated types need to be translated into the universal type space, which will spread virally throughout the program: that either needs to be
done at compile time by Roslyn (the representation change we want to avoid), or it needs to be done by the runtime. The runtime has concerns about avoiding an
MxN problem (where M methods will need to be specialized N times) without whole-program analysis, which is not always available. There's also some argument that,
of all the things associated types can do, the self type is one of the least interesting ones. Consumers of the generic math feature will almost certainly still
need to use a generic type parameter, because unless they're creating a method with one input and no outputs, they will need to constrain each input and output to
be the _same_ associated type, not just _some_ associated self type. IE, using a hypothetical `INumber.this` syntax:

```cs
// How is the compiler to know that the `INumber.self` of the `left` parameter is the same as the `INumber.self` of the `right` parameter, and how does it make
// any assumptions about the return type?
public INumber.self Add(INumber.self left, INumber.self right) => left + right;

// Users would actually need to resort to generics to relate these parameters:
public T Add<T>(T left, T right) where T : INumber.self => left + right;
```

Given that we see the _vast_ majority of the usages of the self type being consumption, not definition, we're unsure the potentially significant cost of the
associated->universal type translation actually buys the user anything.

#### Conclusions

We're going to have a small group explore this space more and make revisions to the proposal before coming back to LDM.
