示例#1
0
        /// <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);
        }
示例#2
0
        /// <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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }