Example #1
0
        private static bool CanCastToClass(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            TypeDesc curType = thisType;

            if (curType.IsInterface && otherType.IsObject)
            {
                return(true);
            }

            // If the target type has variant type parameters, we take a slower path
            if (curType.HasVariance)
            {
                // First chase inheritance hierarchy until we hit a class that only differs in its instantiation
                do
                {
                    if (curType == otherType)
                    {
                        return(true);
                    }

                    if (curType.CanCastByVarianceToInterfaceOrDelegate(otherType, protect))
                    {
                        return(true);
                    }

                    curType = curType.BaseType;
                }while (curType != null);
            }
            else
            {
                // If there are no variant type parameters, just chase the hierarchy

                // Allow curType to be nullable, which means this method
                // will additionally return true if curType is Nullable<T> && (
                //    currType == otherType
                // OR otherType is System.ValueType or System.Object)

                // Always strip Nullable from the otherType, if present
                if (otherType.IsNullable && !curType.IsNullable)
                {
                    return(thisType.CanCastTo(otherType.Instantiation[0]));
                }

                do
                {
                    if (curType == otherType)
                    {
                        return(true);
                    }

                    curType = curType.BaseType;
                } while (curType != null);
            }

            return(false);
        }
        private static bool VerifyGenericParamConstraint(InstantiationContext genericParamContext, GenericParameterDesc genericParam,
                                                         InstantiationContext instantiationParamContext, TypeDesc instantiationParam)
        {
            GenericConstraints constraints = genericParam.Constraints;

            // Check class constraint
            if ((constraints & GenericConstraints.ReferenceTypeConstraint) != 0)
            {
                if (!instantiationParam.IsGCPointer &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.ReferenceTypeConstraint))
                {
                    return(false);
                }
            }

            // Check default constructor constraint
            if ((constraints & GenericConstraints.DefaultConstructorConstraint) != 0)
            {
                if (!instantiationParam.HasExplicitOrImplicitDefaultConstructor() &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.DefaultConstructorConstraint))
                {
                    return(false);
                }
            }

            // Check struct constraint
            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                if ((!instantiationParam.IsValueType || instantiationParam.IsNullable) &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.NotNullableValueTypeConstraint))
                {
                    return(false);
                }
            }

            var instantiatedConstraints = new ArrayBuilder <TypeDesc>();

            GetInstantiatedConstraintsRecursive(instantiationParamContext, instantiationParam, ref instantiatedConstraints);

            foreach (var constraintType in genericParam.TypeConstraints)
            {
                var instantiatedType = constraintType.InstantiateSignature(genericParamContext.TypeInstantiation, genericParamContext.MethodInstantiation);
                if (CanCastConstraint(ref instantiatedConstraints, instantiatedType))
                {
                    continue;
                }

                if (!instantiationParam.CanCastTo(instantiatedType))
                {
                    return(false);
                }
            }

            return(true);
        }
        private static bool VerifyGenericParamConstraint(Instantiation typeInstantiation, Instantiation methodInstantiation, GenericParameterDesc genericParam, TypeDesc instantiationParam)
        {
            // Check class constraint
            if (genericParam.HasReferenceTypeConstraint && !instantiationParam.IsGCPointer)
            {
                return(false);
            }

            // Check default constructor constraint
            if (genericParam.HasDefaultConstructorConstraint)
            {
                if (!instantiationParam.IsDefType)
                {
                    return(false);
                }

                if (!instantiationParam.IsValueType && instantiationParam.GetDefaultConstructor() == null)
                {
                    return(false);
                }
            }

            // Check struct constraint
            if (genericParam.HasNotNullableValueTypeConstraint)
            {
                if (!instantiationParam.IsValueType)
                {
                    return(false);
                }

                if (instantiationParam.IsNullable)
                {
                    return(false);
                }
            }

            foreach (var constraintType in genericParam.TypeConstraints)
            {
                var instantiatedType = constraintType.InstantiateSignature(typeInstantiation, methodInstantiation);
                if (!instantiationParam.CanCastTo(instantiatedType))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #4
0
        /// <summary>
        /// Checks if two types are compatible according to compatible-with as described in ECMA 335 I.8.7.1
        /// Most of the checks are performed by the CanCastTo, but some cases are pre-filtered out.
        /// </summary>
        public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType)
        {
            // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1
            bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType;

            if (isCastFromValueTypeToReferenceType)
            {
                return(false);
            }

            // Managed pointers are compatible only if they are pointer-element-compatible-with as described in ECMA I.8.7.2
            if (thisType.IsByRef && otherType.IsByRef)
            {
                return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType()));
            }

            // Unmanaged pointers are handled the same way as managed pointers
            if (thisType.IsPointer && otherType.IsPointer)
            {
                return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType()));
            }

            // Function pointers are compatible only if they are method-signature-compatible-with as described in ECMA I.8.7.1
            if (thisType.IsFunctionPointer && otherType.IsFunctionPointer)
            {
                return(IsMethodSignatureCompatibleWith(thisType, otherType));
            }

            // None of the types can be a managed pointer, a pointer or a function pointer here,
            // all the valid cases were handled above.
            if (thisType.IsByRef || otherType.IsByRef ||
                thisType.IsPointer || otherType.IsPointer ||
                thisType.IsFunctionPointer || otherType.IsFunctionPointer)
            {
                return(false);
            }

            // Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1
            bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]);

            if (isCastFromNullableOfTtoT)
            {
                return(false);
            }

            return(otherType.CanCastTo(thisType));
        }
Example #5
0
        private static bool VerifyGenericParamConstraint(Instantiation typeInstantiation, Instantiation methodInstantiation, GenericParameterDesc genericParam, TypeDesc instantiationParam)
        {
            GenericConstraints constraints = genericParam.Constraints;

            // Check class constraint
            if ((constraints & GenericConstraints.ReferenceTypeConstraint) != 0)
            {
                if (!instantiationParam.IsGCPointer)
                {
                    return(false);
                }
            }

            // Check default constructor constraint
            if ((constraints & GenericConstraints.DefaultConstructorConstraint) != 0)
            {
                if (!instantiationParam.HasExplicitOrImplicitDefaultConstructor())
                {
                    return(false);
                }
            }

            // Check struct constraint
            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                if (!instantiationParam.IsValueType)
                {
                    return(false);
                }

                if (instantiationParam.IsNullable)
                {
                    return(false);
                }
            }

            foreach (var constraintType in genericParam.TypeConstraints)
            {
                var instantiatedType = constraintType.InstantiateSignature(typeInstantiation, methodInstantiation);
                if (!instantiationParam.CanCastTo(instantiatedType))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #6
0
        public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType)
        {
            // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1
            bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType;

            if (isCastFromValueTypeToReferenceType)
            {
                return(false);
            }

            // Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1
            bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]);

            if (isCastFromNullableOfTtoT)
            {
                return(false);
            }

            return(otherType.CanCastTo(thisType));
        }