private static bool ImplementsIEquatable(RuntimeTypeHandle t) { int interfaceCount = RuntimeAugments.GetInterfaceCount(t); for (int i = 0; i < interfaceCount; i++) { RuntimeTypeHandle interfaceType = RuntimeAugments.GetInterface(t, i); if (!RuntimeAugments.IsGenericType(interfaceType)) { continue; } RuntimeTypeHandle genericDefinition; RuntimeTypeHandle[] genericTypeArgs; genericDefinition = RuntimeAugments.GetGenericInstantiation(interfaceType, out genericTypeArgs); if (genericDefinition.Equals(typeof(IEquatable <>).TypeHandle)) { if (genericTypeArgs.Length != 1) { continue; } if (genericTypeArgs[0].Equals(t)) { return(true); } } } return(false); }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc type) { int numInterfaces = RuntimeAugments.GetInterfaceCount(type.RuntimeTypeHandle); DefType[] interfaces = new DefType[numInterfaces]; for (int i = 0; i < numInterfaces; i++) { RuntimeTypeHandle itfHandle = RuntimeAugments.GetInterface(type.RuntimeTypeHandle, i); TypeDesc itfType = type.Context.ResolveRuntimeTypeHandle(itfHandle); interfaces[i] = (DefType)itfType; } return(interfaces); }
public override Type[] GetInterfaces() { int count = RuntimeAugments.GetInterfaceCount(_typeHandle); if (count == 0) { return(Type.EmptyTypes); } Type[] result = new Type[count]; for (int i = 0; i < result.Length; i++) { result[i] = GetRuntimeTypeInfo(RuntimeAugments.GetInterface(_typeHandle, i)); } return(result); }
private static bool ImplementsIComparable(RuntimeTypeHandle t) { int interfaceCount = RuntimeAugments.GetInterfaceCount(t); for (int i = 0; i < interfaceCount; i++) { RuntimeTypeHandle interfaceType = RuntimeAugments.GetInterface(t, i); if (!RuntimeAugments.IsGenericType(interfaceType)) { continue; } RuntimeTypeHandle genericDefinition; RuntimeTypeHandle[] genericTypeArgs; bool success = TypeLoaderEnvironment.Instance.TryGetConstructedGenericTypeComponents(interfaceType, out genericDefinition, out genericTypeArgs); if (success) { if (genericDefinition.Equals(typeof(IComparable <>).TypeHandle)) { if (genericTypeArgs.Length != 1) { continue; } if (RuntimeAugments.IsValueType(t)) { if (genericTypeArgs[0].Equals(t)) { return(true); } } else if (RuntimeAugments.IsAssignableFrom(genericTypeArgs[0], t)) { return(true); } } } } return(false); }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc type) { TypeBuilderState state = type.GetOrCreateTypeBuilderState(); int totalInterfaces = RuntimeAugments.GetInterfaceCount(state.TemplateType.RuntimeTypeHandle); TypeLoaderLogger.WriteLine("Building runtime interfaces for type " + type.ToString() + " (total interfaces = " + totalInterfaces.LowLevelToString() + ") ..."); DefType[] interfaces = new DefType[totalInterfaces]; int numInterfaces = 0; // // Copy over all interfaces from base class // if (type.BaseType != null) { foreach (var baseInterface in type.BaseType.RuntimeInterfaces) { // There should be no duplicates Debug.Assert(!InterfaceInSet(interfaces, numInterfaces, baseInterface)); interfaces[numInterfaces++] = baseInterface; TypeLoaderLogger.WriteLine(" -> Added basetype interface " + baseInterface.ToString() + " on type " + type.ToString()); } } NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo(); NativeParser interfaceParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.ImplementedInterfaces); TypeDesc[] implementedInterfaces; if (!interfaceParser.IsNull) { implementedInterfaces = state.NativeLayoutInfo.LoadContext.GetTypeSequence(ref interfaceParser); } else { implementedInterfaces = TypeDesc.EmptyTypes; } // Note that the order in which the interfaces are added to the list is same as the order in which the MDIL binder adds them. // It is required for correctness foreach (TypeDesc interfaceType in implementedInterfaces) { DefType interfaceTypeAsDefType = (DefType)interfaceType; // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, interfaceTypeAsDefType)) { continue; } interfaces[numInterfaces++] = interfaceTypeAsDefType; TypeLoaderLogger.WriteLine(" -> Added interface " + interfaceTypeAsDefType.ToString() + " on type " + type.ToString()); foreach (var inheritedInterface in interfaceTypeAsDefType.RuntimeInterfaces) { // Skip duplicates if (InterfaceInSet(interfaces, numInterfaces, inheritedInterface)) { continue; } interfaces[numInterfaces++] = inheritedInterface; TypeLoaderLogger.WriteLine(" -> Added inherited interface " + inheritedInterface.ToString() + " on type " + type.ToString()); } } // TODO: Handle the screwy cases of generic interface folding Debug.Assert(numInterfaces == totalInterfaces, "Unexpected number of interfaces"); return(interfaces); }
private bool FindMatchingInterfaceSlot(NativeFormatModuleInfo module, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle instanceTypeHandle, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch, bool defaultMethods) { uint numTargetImplementations = entryParser.GetUnsigned(); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" :: Declaring type = " + GetTypeNameDebug(declaringType)); Debug.WriteLine(" :: Target type = " + GetTypeNameDebug(openTargetTypeHandle)); #endif for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = entryParser.GetUnsigned(); MethodNameAndSignature targetMethodNameAndSignature = null; RuntimeTypeHandle targetTypeHandle = default; bool isDefaultInterfaceMethodImplementation; if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction) { targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif } else { isDefaultInterfaceMethodImplementation = true; } uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current implementing type = " + GetTypeNameDebug(implementingTypeHandle)); #endif uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle) || defaultMethods != isDefaultInterfaceMethodImplementation) { // Skip over signatures data for (uint l = 0; l < numIfaceSigs; l++) { entryParser.GetUnsigned(); } continue; } for (uint l = 0; l < numIfaceSigs; l++) { RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle); NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned()); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(ref ifaceSigParser, module.Handle, targetTypeInstantiation, null, out currentIfaceTypeHandle)) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" -> Current interface on type = " + GetTypeNameDebug(currentIfaceTypeHandle)); #endif Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if GVM_RESOLUTION_TRACE Debug.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif if (targetMethodNameAndSignature == null) { if (nameAndSigToken == SpecialGVMInterfaceEntry.Diamond) { throw new AmbiguousImplementationException(); } else { Debug.Assert(nameAndSigToken == SpecialGVMInterfaceEntry.Reabstraction); throw new EntryPointNotFoundException(); } } // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller if (!RuntimeAugments.IsInterface(targetTypeHandle) || !RuntimeAugments.IsGenericTypeDefinition(targetTypeHandle)) { // Not a default interface method or default interface method on a non-generic type. // We have a usable type handle. declaringType = targetTypeHandle; } else if (RuntimeAugments.IsGenericType(currentIfaceTypeHandle) && RuntimeAugments.GetGenericDefinition(currentIfaceTypeHandle).Equals(targetTypeHandle)) { // Default interface method implemented on the same type that declared the slot. // Use the instantiation as-is from what we found. declaringType = currentIfaceTypeHandle; } else { declaringType = default; // Default interface method implemented on a different generic interface. // We need to find a usable instantiation. There should be only one match because we // would be dealing with a diamond otherwise. int numInstanceInterfaces = RuntimeAugments.GetInterfaceCount(instanceTypeHandle); for (int instIntfIndex = 0; instIntfIndex < numInstanceInterfaces; instIntfIndex++) { RuntimeTypeHandle instIntf = RuntimeAugments.GetInterface(instanceTypeHandle, instIntfIndex); if (RuntimeAugments.IsGenericType(instIntf) && RuntimeAugments.GetGenericDefinition(instIntf).Equals(targetTypeHandle)) { // Got a potential interface. Check if the implementing interface is in the interface // list. We don't want IsAssignableFrom because we need an exact match. int numIntInterfaces = RuntimeAugments.GetInterfaceCount(instIntf); for (int intIntfIndex = 0; intIntfIndex < numIntInterfaces; intIntfIndex++) { if (RuntimeAugments.GetInterface(instIntf, intIntfIndex).Equals(currentIfaceTypeHandle)) { Debug.Assert(declaringType.IsNull()); declaringType = instIntf; #if !DEBUG break; #endif } } #if !DEBUG if (!declaringType.IsNull()) { break; } #endif } } Debug.Assert(!declaringType.IsNull()); } methodNameAndSignature = targetMethodNameAndSignature; return(true); } } } } } return(false); }