/// <summary> /// Try to resolve a given virtual static interface method on a given constrained type and return the resolved method or null when not found. /// </summary> /// <param name="constrainedType">Type to attempt method resolution on</param> /// <param name="interfaceMethod">Method to resolve</param> /// <returns>MethodDesc of the resolved method or null when not found (runtime lookup must be used)</returns> private static MethodDesc TryResolveVirtualStaticMethodOnThisType(MetadataType constrainedType, MethodDesc interfaceMethod) { Debug.Assert(interfaceMethod.Signature.IsStatic); MethodImplRecord[] possibleImpls = constrainedType.FindMethodsImplWithMatchingDeclName(interfaceMethod.Name); if (possibleImpls == null) { return(null); } MethodDesc interfaceMethodDefinition = interfaceMethod.GetMethodDefinition(); foreach (MethodImplRecord methodImpl in possibleImpls) { if (methodImpl.Decl == interfaceMethodDefinition) { MethodDesc resolvedMethodImpl = methodImpl.Body; if (interfaceMethod != interfaceMethodDefinition) { resolvedMethodImpl = resolvedMethodImpl.MakeInstantiatedMethod(interfaceMethod.Instantiation); } return(resolvedMethodImpl); } } return(null); }
/// <summary> /// Resolve a virtual function call (to a virtual method, not an interface method) /// </summary> /// <param name="targetMethod"></param> /// <param name="objectType"></param> /// <returns>The override of the virtual method that should be called</returns> private static MethodDesc FindVirtualFunctionTargetMethodOnObjectType(MethodDesc targetMethod, MetadataType objectType) { // Step 1, convert objectType to uninstantiated form MetadataType uninstantiatedType = objectType; MethodDesc initialTargetMethod = targetMethod; InstantiatedType initialInstantiatedType = objectType as InstantiatedType; if (initialInstantiatedType != null) { uninstantiatedType = (MetadataType)initialInstantiatedType.GetTypeDefinition(); } // Step 2, convert targetMethod to method in type hierarchy of uninstantiated form targetMethod = targetMethod.GetMethodDefinition(); if (uninstantiatedType != objectType) { targetMethod = uninstantiatedType.FindMethodOnTypeWithMatchingTypicalMethod(targetMethod); } // Step 3, find unification group of target method UnificationGroup group = new UnificationGroup(FindSlotDefiningMethodForVirtualMethod(targetMethod)); FindBaseUnificationGroup(uninstantiatedType, group); // Step 4, name/sig match virtual function resolve MethodDesc resolutionTarget = FindNameSigOverrideForVirtualMethod(group.DefiningMethod, uninstantiatedType); if (resolutionTarget == null) { return(null); } // Step 5, convert resolution target from uninstantiated form target to objecttype target, // and instantiate as appropriate if (uninstantiatedType != objectType) { resolutionTarget = objectType.FindMethodOnTypeWithMatchingTypicalMethod(resolutionTarget); } if (initialTargetMethod.HasInstantiation) { resolutionTarget = resolutionTarget.MakeInstantiatedMethod(initialTargetMethod.Instantiation); } return(resolutionTarget); }
public static DefaultInterfaceMethodResolution ResolveVariantInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl) { Debug.Assert(interfaceMethod.Signature.IsStatic); MetadataType interfaceType = (MetadataType)interfaceMethod.OwningType; bool foundInterface = IsInterfaceImplementedOnType(currentType, interfaceType); if (foundInterface) { DefaultInterfaceMethodResolution resolution = ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, currentType, out impl); if (resolution != DefaultInterfaceMethodResolution.None) { return(resolution); } } MethodDesc interfaceMethodDefinition = interfaceMethod.GetMethodDefinition(); foreach (TypeDesc iface in currentType.RuntimeInterfaces) { if (iface.HasSameTypeDefinition(interfaceType) && iface.CanCastTo(interfaceType)) { MethodDesc variantMethod = iface.FindMethodOnTypeWithMatchingTypicalMethod(interfaceMethodDefinition); Debug.Assert(variantMethod != null); if (interfaceMethod != interfaceMethodDefinition) { variantMethod = variantMethod.MakeInstantiatedMethod(interfaceMethod.Instantiation); } DefaultInterfaceMethodResolution resolution = ResolveInterfaceMethodToDefaultImplementationOnType(variantMethod, currentType, out impl); if (resolution != DefaultInterfaceMethodResolution.None) { return(resolution); } } } impl = null; return(DefaultInterfaceMethodResolution.None); }
private static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl) { TypeDesc interfaceMethodOwningType = interfaceMethod.OwningType; MetadataType mostSpecificInterface = null; bool diamondCase = false; impl = null; MethodDesc interfaceMethodDefinition = interfaceMethod.GetMethodDefinition(); DefType[] consideredInterfaces; if (!currentType.IsInterface) { // If this is not an interface, only things on the interface list could provide // default implementations. consideredInterfaces = currentType.RuntimeInterfaces; } else { // If we're asking about an interface, include the interface in the list. consideredInterfaces = new DefType[currentType.RuntimeInterfaces.Length + 1]; Array.Copy(currentType.RuntimeInterfaces, consideredInterfaces, currentType.RuntimeInterfaces.Length); consideredInterfaces[consideredInterfaces.Length - 1] = (DefType)currentType.InstantiateAsOpen(); } foreach (MetadataType runtimeInterface in consideredInterfaces) { if (runtimeInterface == interfaceMethodOwningType) { // Also consider the default interface method implementation on the interface itself // if we don't have anything else yet if (mostSpecificInterface == null && !interfaceMethod.IsAbstract) { mostSpecificInterface = runtimeInterface; impl = interfaceMethodDefinition; } } else if (Array.IndexOf(runtimeInterface.RuntimeInterfaces, interfaceMethodOwningType) != -1) { // This interface might provide a default implementation MethodImplRecord[] possibleImpls = runtimeInterface.FindMethodsImplWithMatchingDeclName(interfaceMethod.Name); if (possibleImpls != null) { foreach (MethodImplRecord implRecord in possibleImpls) { if (implRecord.Decl == interfaceMethodDefinition) { // This interface provides a default implementation. // Is it also most specific? if (mostSpecificInterface == null || Array.IndexOf(runtimeInterface.RuntimeInterfaces, mostSpecificInterface) != -1) { mostSpecificInterface = runtimeInterface; impl = implRecord.Body; diamondCase = false; } else if (Array.IndexOf(mostSpecificInterface.RuntimeInterfaces, runtimeInterface) == -1) { diamondCase = true; } break; } } } } } if (diamondCase) { impl = null; return(DefaultInterfaceMethodResolution.Diamond); } else if (impl == null) { return(DefaultInterfaceMethodResolution.None); } else if (impl.IsAbstract) { impl = null; return(DefaultInterfaceMethodResolution.Reabstraction); } if (interfaceMethod != interfaceMethodDefinition) { impl = impl.MakeInstantiatedMethod(interfaceMethod.Instantiation); } return(DefaultInterfaceMethodResolution.DefaultImplementation); }