예제 #1
0
        /// <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&lt;SomeGeneric&lt;int[]&gt;&gt;, 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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        public static TypeDesc GetParameterType(this TypeDesc type)
        {
            ParameterizedType paramType = (ParameterizedType)type;

            return(paramType.ParameterType);
        }
예제 #4
0
        /// <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&lt;object, int[]&gt;,
        ///  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&lt;__Canon, string[]&gt;
        ///
        /// 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);
        }
예제 #5
0
        // 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);
        }