# C# Language Design Meeting for June 29th, 2020

## Agenda

1. [Static interface members](https://github.com/Partydonk/partydonk/issues/1)

## Procedural Note

For the past few years, the LDM notes have been compiled by the wonderful Andy Gocke (@agocke).
Andy is taking the next step in his career and moving to be the lead of the CLR App Model team
as of today, and as such will be moving to LDT emeritus status, joining the ranks of our other
former LDT members who form our advisory council. We thank him for all his hard work during his
time as notetaker, collating the sometimes inane rambling of the LDM in a set of readable
arguments and decisions.

At this point Fred Silberberg (@333fred) will be the new LDM notetaker. While I'll try to keep
up much of the same spirit as Andy, I am not going to try to match his exact style or formatting,
so there could be some changes in the exact formatting of the notes. I'll additionally apologize
in advance as the notes inevitably end up delayed in the first few weeks as I settle in. And now,
on to the meeting notes!

## Quote of the Day

"So we spent these last 10 years making it so we can come back to this. We actually never forgot,
[.NET Core] has all been a ploy to get statics into interfaces."

## Discussion

Today @abock and @migueldeicaza presented their work on Partydonk over the past year, bringing
abstract interface members to C# and the Mono runtime in a proof of concept. I did not take notes
on the specific slides: all of that material is available publicly on the partydonk repo
[here](https://github.com/Partydonk/partydonk/blob/master/Generic%20Math/Generic%20Math%20in%20.NET%20-%20Contractual%20Static%20Interface%20Members%20in%20CSharp.pdf).

Overall, the LDT members had a very positive reception to this work: in particular, they arrived
at many of the same conclusions @CarolEidt had in her exploration of this space 10 years ago:
much of the runtime work falls out from allowing `abstract static` in CIL and emitting constrained
calls to such members during compilation. From a language perspective, there's still a bit of work
to do. `override` on `abstract` static members defined in interfaces isn't particularly nice from
a regularity with instance members perspective. We will also have to do design work around explicit
implementations: it could all fall out from existing rules, but will need a critical eye to make
sure that the consequences of explicitly implementing an abstract member, and what that really means.

The existing code uses a `TSelf` generic parameter in what could be considered kind of an unfortunate
syntax:

```cs
interface INumeric<TSelf> where TSelf : INumeric<TSelf>
{
    abstract static TSelf Zero { get; }
    abstract static TSelf operator +(TSelf a, TSelf b);
}
```

The `TSelf : where TSelf : INumeric<TSelf>` was suggested in the past to help the prototype make
progress without blocking on associated types, but it's ugly and proliferates through the entire
type hierarchy if left unchecked. A much better solution would be to formally introduce associated
types into the language, something that we've discussed in LDM before and has some support. We should
take those into account here: if we introduce this entire type hierarchy, then in the next C# release
introduce a `TSelf` associated type it would leave an annoying blemish on the language. In particular,
we need to make sure we have a good roadmap for all components involved here: the compiler, the runtime,
and the core libraries. Nonvirtual static members in interfaces have already shipped with C# 8, so we
can't get that back and declared them virtual members of the interface.

We do still have a few language questions: today, you cannot create user-defined operators that involve
interfaces, because doing so would subvert the type system. However, some numeric applications seem
like they would want to be able to do this for constants (see `IExpressibleByIntegerLiteral` and
`IExpressibleByFloatLiteral` in the presentation). If we allow this for the `TSelf` parameter, it seems
like these concerns should be obviated: you're not converting to an interface type, you're converting to
a concrete type and specifying that said conversion must be available for any implementations of the
interface. Additionally there's an interesting correspondance issue: today, any members that are part
of the interface contract are available on an instance of the interface. However, with static methods,
the interface itself doesn't provide them: types that implement the interface provide them, but not the
interface itself. We can certainly come up with new rules to cover this, but we will need to do so.

Some other miscellaneous topics that came up:
* We could use this system to specify constructors with multiple parameters of a specific type. Static
interface members could be implemented by a type calling `new`, which would allow us to improve on the
simple `new()` that we have today.
* Existing language built-in operators would need to be considered to satisfy the constraints of the
numeric interfaces.
