80 lines
5 KiB
Markdown
80 lines
5 KiB
Markdown
# 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.
|