/// <summary> /// Determine if the construction of a type contains one of a given set of types. This is a deep /// scan. For instance, given type MyType<SomeGeneric<int[]>>, and a set of typesToFind /// that includes int, this function will return true. Does not detect the open generics that may be /// instantiated over in this type. IsConstructedOverType would return false if only passed MyType, /// or SomeGeneric for the above examplt. /// </summary> /// <param name="type">type to examine</param> /// <param name="typesToFind">types to search for in the construction of type</param> /// <returns>true if a type in typesToFind is found</returns> public static bool IsConstructedOverType(this TypeDesc type, TypeDesc[] typesToFind) { int directDiscoveryIndex = Array.IndexOf(typesToFind, type); if (directDiscoveryIndex != -1) { return(true); } if (type.HasInstantiation) { for (int instantiationIndex = 0; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { if (type.Instantiation[instantiationIndex].IsConstructedOverType(typesToFind)) { return(true); } } } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; return(parameterizedType.ParameterType.IsConstructedOverType(typesToFind)); } else if (type.IsFunctionPointer) { MethodSignature functionPointerSignature = ((FunctionPointerType)type).Signature; if (functionPointerSignature.ReturnType.IsConstructedOverType(typesToFind)) { return(true); } for (int paramIndex = 0; paramIndex < functionPointerSignature.Length; paramIndex++) { if (functionPointerSignature[paramIndex].IsConstructedOverType(typesToFind)) { return(true); } } } return(false); }
private static bool CanCastParamTo(this ParameterizedType thisType, TypeDesc paramType, StackOverflowProtect protect) { // While boxed value classes inherit from object their // unboxed versions do not. Parameterized types have the // unboxed version, thus, if the from type parameter is value // class then only an exact match/equivalence works. if (thisType.ParameterType == paramType) { return(true); } TypeDesc curTypesParm = thisType.ParameterType; // Object parameters don't need an exact match but only inheritance, check for that TypeDesc fromParamUnderlyingType = curTypesParm.UnderlyingType; if (fromParamUnderlyingType.IsGCPointer) { return(curTypesParm.CanCastToInternal(paramType, protect)); } else if (curTypesParm.IsGenericParameter) { var genericVariableFromParam = (GenericParameterDesc)curTypesParm; if (genericVariableFromParam.HasReferenceTypeConstraint) { return(genericVariableFromParam.CanCastToInternal(paramType, protect)); } } else if (fromParamUnderlyingType.IsPrimitive) { TypeDesc toParamUnderlyingType = paramType.UnderlyingType; if (GetNormalizedIntegralArrayElementType(fromParamUnderlyingType) == GetNormalizedIntegralArrayElementType(toParamUnderlyingType)) { return(true); } } // Anything else is not a match return(false); }
public static TypeDesc GetParameterType(this TypeDesc type) { ParameterizedType paramType = (ParameterizedType)type; return(paramType.ParameterType); }
/// <summary> /// Replace some of the types in a type's construction with a new set of types. This function does not /// support any situation where there is an instantiated generic that is not represented by an /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type. /// /// For instance, Given MyType<object, int[]>, /// an array of types to replace such as {int,object}, and /// an array of replacement types such as {string,__Canon}. /// The result shall be MyType<__Canon, string[]> /// /// This function cannot be used to replace MyType in the above example. /// </summary> public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes) { int directReplacementIndex = Array.IndexOf(typesToReplace, type); if (directReplacementIndex != -1) { return(replacementTypes[directReplacementIndex]); } if (type.HasInstantiation) { TypeDesc[] newInstantiation = null; Debug.Assert(type is InstantiatedType); int instantiationIndex = 0; for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { TypeDesc oldType = type.Instantiation[instantiationIndex]; TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if ((oldType != newType) || (newInstantiation != null)) { if (newInstantiation == null) { newInstantiation = new TypeDesc[type.Instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) { newInstantiation[i] = type.Instantiation[i]; } } newInstantiation[instantiationIndex] = newType; } } if (newInstantiation != null) { return(type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation))); } } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; TypeDesc oldParameter = parameterizedType.ParameterType; TypeDesc newParameter = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if (oldParameter != newParameter) { if (type.IsArray) { ArrayType arrayType = (ArrayType)type; if (arrayType.IsSzArray) { return(type.Context.GetArrayType(newParameter)); } else { return(type.Context.GetArrayType(newParameter, arrayType.Rank)); } } else if (type.IsPointer) { return(type.Context.GetPointerType(newParameter)); } else if (type.IsByRef) { return(type.Context.GetByRefType(newParameter)); } Debug.Fail("Unknown form of type"); } } else if (type.IsFunctionPointer) { MethodSignature oldSig = ((FunctionPointerType)type).Signature; MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig); sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++) { sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); } MethodSignature newSig = sigBuilder.ToSignature(); if (newSig != oldSig) { return(type.Context.GetFunctionPointerType(newSig)); } } return(type); }
// Todo: This is looking up the hierarchy to DefType and ParameterizedType. It should really // call a virtual or an outside type to handle those parts internal bool RetrieveRuntimeTypeHandleIfPossible() { TypeDesc type = this; if (!type.RuntimeTypeHandle.IsNull()) { return(true); } TypeBuilderState state = GetTypeBuilderStateIfExist(); if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle) { return(false); } if (type is DefType) { DefType typeAsDefType = (DefType)type; TypeDesc typeDefinition = typeAsDefType.GetTypeDefinition(); RuntimeTypeHandle typeDefHandle = typeDefinition.RuntimeTypeHandle; if (typeDefHandle.IsNull()) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING NativeFormat.NativeFormatType mdType = typeDefinition as NativeFormat.NativeFormatType; if (mdType != null) { // Look up the runtime type handle in the module metadata if (TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(new QTypeDefinition(mdType.MetadataReader, mdType.Handle), out typeDefHandle)) { typeDefinition.SetRuntimeTypeHandleUnsafe(typeDefHandle); } } #endif #if ECMA_METADATA_SUPPORT Ecma.EcmaType ecmaType = typeDefinition as Ecma.EcmaType; if (ecmaType != null) { // Look up the runtime type handle in the module metadata if (TypeLoaderEnvironment.Instance.TryGetNamedTypeForMetadata(new QTypeDefinition(ecmaType.MetadataReader, ecmaType.Handle), out typeDefHandle)) { typeDefinition.SetRuntimeTypeHandleUnsafe(typeDefHandle); } } #endif } if (!typeDefHandle.IsNull()) { Instantiation instantiation = typeAsDefType.Instantiation; if ((instantiation.Length > 0) && !typeAsDefType.IsGenericDefinition) { // Generic type. First make sure we have type handles for the arguments, then check // the instantiation. bool argumentsRegistered = true; bool arrayArgumentsFound = false; for (int i = 0; i < instantiation.Length; i++) { if (!instantiation[i].RetrieveRuntimeTypeHandleIfPossible()) { argumentsRegistered = false; arrayArgumentsFound = arrayArgumentsFound || (instantiation[i] is ArrayType); } } RuntimeTypeHandle rtth; // If at least one of the arguments is not known to the runtime, we take a slower // path to compare the current type we need a handle for to the list of generic // types statically available, by loading them as DefTypes and doing a DefType comparaison if ((argumentsRegistered && TypeLoaderEnvironment.Instance.TryLookupConstructedGenericTypeForComponents(new TypeLoaderEnvironment.HandleBasedGenericTypeLookup(typeAsDefType), out rtth)) || (arrayArgumentsFound && TypeLoaderEnvironment.Instance.TryLookupConstructedGenericTypeForComponents(new TypeLoaderEnvironment.DefTypeBasedGenericTypeLookup(typeAsDefType), out rtth))) { typeAsDefType.SetRuntimeTypeHandleUnsafe(rtth); return(true); } } else { // Nongeneric, or generic type def types are just the type handle of the type definition as found above type.SetRuntimeTypeHandleUnsafe(typeDefHandle); return(true); } } } else if (type is ParameterizedType) { ParameterizedType typeAsParameterType = (ParameterizedType)type; if (typeAsParameterType.ParameterType.RetrieveRuntimeTypeHandleIfPossible()) { RuntimeTypeHandle rtth; if ((type is ArrayType && (TypeLoaderEnvironment.Instance.TryGetArrayTypeForElementType_LookupOnly(typeAsParameterType.ParameterType.RuntimeTypeHandle, type.IsMdArray, type.IsMdArray ? ((ArrayType)type).Rank : -1, out rtth) || TypeLoaderEnvironment.Instance.TryGetArrayTypeHandleForNonDynamicArrayTypeFromTemplateTable(type as ArrayType, out rtth))) || (type is PointerType && TypeSystemContext.PointerTypesCache.TryGetValue(typeAsParameterType.ParameterType.RuntimeTypeHandle, out rtth))) { typeAsParameterType.SetRuntimeTypeHandleUnsafe(rtth); return(true); } else if (type is ByRefType) { // Byref types don't have any associated type handles, so return success at this point // since we were able to resolve the typehandle of the element type return(true); } } } else if (type is SignatureVariable) { // SignatureVariables do not have RuntimeTypeHandles } else { Debug.Assert(false); } // Make a note on the type build state that we have attempted to retrieve RuntimeTypeHandle but there is not one GetOrCreateTypeBuilderState().AttemptedAndFailedToRetrieveTypeHandle = true; return(false); }