Add meeting notes for 2017-03-23 CLR behavior for default methods (#407)

This commit is contained in:
Neal Gafter 2017-04-04 17:47:46 -07:00 committed by GitHub
parent dcabca1a59
commit dc26f4c368

View file

@ -0,0 +1,133 @@
2017-03-23 CLR Behavior for Default Interface Methods
==========================================
Met today with
- [Neal Gafter](https://github.com/gafter)
- [David Wrighton](https://github.com/davidwrighton)
- [Aleksey Tsingauz](https://github.com/AlekseyTs)
- [Yi Zhang (CLR)](https://github.com/yizhang82)
To discuss the CLR handling of default interface methods.
### (1) Runtime handling of ambiguities
Question (1) is about what the CLR should do when the runtime does not find a most specific override for an interface method. For example, if this program is compiled (each interface being in a separate assembly)
``` c#
public interface IA
{
void M();
}
public interface IB : IA
{
override void IA.M() { WriteLine("IB"); }
}
public interface IC : IA
{
}
class C : IB, IC
{
static void Main()
{
IA a = new C();
a.M();
}
}
```
and then subsequently `IC` is changed
``` c#
public interface IC : IA
{
override void IA.M() { WriteLine("IB"); }
}
```
This would cause an error at compile-time if class `C` were recompiled (because there is no most specific override for `IA.M`). However, what happens if this program is run without recompiling `C`?
There are two most choices:
1. The runtime selects, deterministically, between the implementations of `IA.M` in `IB` and `IC`; or
2. The runtime fails at some time before this invocation is run.
a. At load time; or
b. At the time of the invocation
We did not have consensus which approach is preferred; there are advantages and disadvantages to either. We will defer this issue until it can be discussed in a larger group.
### Static methods
Static methods are already permitted in interfaces.
### Protection levels
From the point of view of the CLR, once we start accepting a protection level other than private, we might as well accept all of them. The semantics are clear.
With the possible exception of `protected` and its related protection levels. We would need to clearly define both the language and runtime constraints implied by this protection level. For example, is a `protected` member in an interface accessible in a class that implements the interface? What would be the syntax in source (note that interface members are not inherited into classes that implement them)? What would be the verifiable form of the generated IL?
We tentatively agreed that the CLR will accept protection levels other than `public` in interfaces, but open questions remain about `protected`.
### Sealed override
It is an open question whether a `sealed override` should be permitted within an interface. Given the most specific override rule, such code could prevent unrelated sister interfaces from implementing the method.
If it were permitted, we need to check that there is a way to represent it in IL.
### Non-virtual methods in interfaces
Non-virtual methods in interfaces are not a problem for the CLR, presuming we have a way to represent them. We need to check that existing interface methods have a `newslot` bit set. We think so. If so, then we would simply omit that from non-virtual methods.
### Implicit overrides in interfaces
We agree that the compiler-generated IL for an "implicit" override
``` c#
public interface IA
{
void M();
}
public interface IB : IA
{
override void M() { WriteLine("IB"); }
}
```
should be roughly the same as for an "explicit" override
``` c#
public interface IB : IA
{
override void IA.M() { WriteLine("IB"); }
}
```
In both cases the compiler produces a `methodimpl` record for the overridden method(s). The CLR will not consider a method in an interface to be an implementation of another method without the `methodimpl` bit. We should confirm that we are OK with the binary compatibility implications of this.
All override declarations should omit the `newslot` bit to ensure no new vtable slot is allocated.
### Open Question: Which interfaces are searched
There is an open question which interfaces are searched for implementations, and in which order. For example, if we have
``` c#
interface IA { void M() {} }
interface IB: IA { override void M() {} }
class Base : IB { }
class Derived : Base, IA { }
```
Then is the override appearing in `IB` the final override selected for class `Derived`, even though `IB` does not appear in the interface list for `Derived`?
### Open Question: Diamond Inheritance between Class and Interface
What should occur in cases involving diamond inheritance with classes and interfaces:
``` c#
interface IA { void M() {} }
interface IB: IA { override void M() {} }
class Base : IA { void IA.M() { } }
class Derived : Base, IB { }
```
In this case neither `Base` nor `IB` is a subtype of the other. Is class `Derived` legal? If so, what is its implementation of `IA.M`?