Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
78 lines (53 sloc) 3.69 KB

Interfaces API surface on Type System

There are two different sets of interfaces a type implements. Explicit interfaces are the ones that are explicitly present in metadata, and the runtimeinterfaces are the ones that the type actually implements. The distinction is important due to explicit vs implicit interface implementation causing interface dispatch behavior to vary, as an explicit implementation will always attempt to bind, but an implicit or inherited interface implementation will only attempt to match if the base type does not provide an implementation for that particular interface.

Explicit interfaces

The explicitly implemented interfaces of this type. These are the interfaces which are described as implemented by the typedef record of this type. (Does not include interfaces implemented due to interface to interface dependencies, or interfaces implemented on base types that are not called out as implemented via the InterfaceImpl entries associated with the typedef.

API

public abstract partial class MetadataType : DefType
{
    public abstract DefType[] ExplicitlyImplementedInterfaces
    {
        get;
    }
}

Algorithm

Read the list of interfaces from the metadata and return it instantiated.

Runtime interfaces

The runtime interface list of this type. This is the set of interfaces that the type implements for the purpose of interface casting and dispatch. Includes the contents the ExplicitlyImplementedInterfaces list as well as any interfaces implemented on base types or as a result of implementation of other interfaces on the ExplitlyImplmentedInterfaces list.

NOTE: Ordering in this list is particular and detailed.

  • If a type has a base type, all of the interfaces from the base type must be expressed in the exact same location within the array.
  • If a type is generic, its interface list must be constructed to be equivalent to the interface list of the open generic type that is then instantiated over whatever the generic parameters are. This may result in duplicates within the interface list.
  • Outside of the duplicates due to the above rule, duplicates are forbidden.

Interface order is required to be stable in this way as interface order in this list affects the behavior of variant interface dispatch, and for shared generics, the index is important as the index to interface mapping is shared between multiple implementation of a generic type which implements interfaces.

API

public abstract partial class TypeDesc
{
	public abstract DefType[] RuntimeInterfaces
  {
    	get;
  }
}

MetadataType Algorithm

For interface types Take the list of ExplicitlyImplementedInterfaces

For non-instantiated types or non-generic types

ComputeInterfaces

  1. Start with the RuntimeInterfaces from the base type. If the base type is null, start with the empty list.
  2. Check ExplicitlyImplementedInterfaces list for duplicates. Such duplicates are not allowed. Throw an error if found.
  3. Foreach entry in ExplicitlyImplementedInterfaces call BuildPostOrderInterfaceList (Note that the implementation uses RuntimeInterfaces here to support conditions where the interface type is not metadata defined)

BuildPostOrderInterfaceList(DefType currentInterface, List implementedInterfaces)

if (implementedInterfaces.Contains(currentInterface) return;
foreach (DefType iface in currentInterface.ExplicitlyImplementedInterfaces)
{
	BuildPostOrderInterfaceList(iface, implementedInterfaces);
}
implementedInterfaces.Add(iface);

For instantiated generic types

  1. Determine the RuntimeInterfaces for the open generic type.
  2. Instantiatiate each interface

For array types

  1. Compute the interface list for Array. Use that.