Example #1
0
        private static bool CanCastToInternal(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (thisType == otherType)
            {
                return true;
            }

            switch (thisType.Category)
            {
                case TypeFlags.GenericParameter:
                    return ((GenericParameterDesc)thisType).CanCastGenericParameterTo(otherType, protect);

                case TypeFlags.Array:
                case TypeFlags.SzArray:
                    return ((ArrayType)thisType).CanCastArrayTo(otherType, protect);

                default:
                    Debug.Assert(thisType.IsDefType);
                    return thisType.CanCastToClassOrInterface(otherType, protect);
            }            
        }
Example #2
0
        private static bool CanCastGenericParameterTo(this GenericParameterDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            // A boxed variable type can be cast to any of its constraints, or object, if none are specified
            if (otherType.IsObject)
            {
                return true;
            }

            if (thisType.HasNotNullableValueTypeConstraint &&
                otherType.IsWellKnownType(WellKnownType.ValueType))
            {
                return true;
            }

            foreach (var typeConstraint in thisType.TypeConstraints)
            {
                if (typeConstraint.CanCastToInternal(otherType, protect))
                {
                    return true;
                }
            }

            return false;
        }
Example #3
0
        private static bool CanCastArrayTo(this ArrayType thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            // Casting the array to one of the base types or interfaces?
            if (otherType.IsDefType)
            {
                return thisType.CanCastToClassOrInterface(otherType, protect);
            }

            // Casting array to something else (between SzArray and Array, for example)?
            if (thisType.Category != otherType.Category)
            {
                return false;
            }

            ArrayType otherArrayType = (ArrayType)otherType;

            // Check ranks if we're casting multidim arrays
            if (!thisType.IsSzArray && thisType.Rank != otherArrayType.Rank)
            {
                return false;
            }

            return thisType.CanCastParamTo(otherArrayType.ParameterType, protect);
        }
Example #4
0
 private static bool CanCastToClassOrInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
 {
     if (otherType.IsInterface)
     {
         return(thisType.CanCastToInterface(otherType, protect));
     }
     else
     {
         return(thisType.CanCastToClass(otherType, protect));
     }
 }
Example #5
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 (toParamUnderlyingType.IsPrimitive)
                {
                    if (toParamUnderlyingType == fromParamUnderlyingType)
                    {
                        return(true);
                    }

                    if (ArePrimitveTypesEquivalentSize(fromParamUnderlyingType, toParamUnderlyingType))
                    {
                        return(true);
                    }
                }
            }

            // Anything else is not a match
            return(false);
        }
Example #6
0
        private static bool CanCastArrayTo(this ArrayType thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            // Casting the array to one of the base types or interfaces?
            if (otherType.IsDefType)
            {
                return(thisType.CanCastToClassOrInterface(otherType, protect));
            }

            // Casting array to something else (between SzArray and Array, for example)?
            if (thisType.Category != otherType.Category)
            {
                // An SzArray is castable to MdArray rank 1. We follow the same casting rules as SzArray to SzArray.
                if (thisType.Category == TypeFlags.SzArray &&
                    otherType.Category == TypeFlags.Array &&
                    ((ArrayType)otherType).Rank == 1)
                {
                    return(thisType.CanCastParamTo(((ArrayType)otherType).ParameterType, protect));
                }

                return(false);
            }

            ArrayType otherArrayType = (ArrayType)otherType;

            // Check ranks if we're casting multidim arrays
            if (!thisType.IsSzArray && thisType.Rank != otherArrayType.Rank)
            {
                return(false);
            }

            return(thisType.CanCastParamTo(otherArrayType.ParameterType, protect));
        }
Example #7
0
        private static bool CanCastGenericParameterTo(this GenericParameterDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            // A boxed variable type can be cast to any of its constraints, or object, if none are specified
            if (otherType.IsObject)
            {
                return(true);
            }

            if (thisType.HasNotNullableValueTypeConstraint &&
                otherType.IsWellKnownType(WellKnownType.ValueType))
            {
                return(true);
            }

            foreach (var typeConstraint in thisType.TypeConstraints)
            {
                if (typeConstraint.CanCastToInternal(otherType, protect))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #8
0
        private static bool CanCastToInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (!otherType.HasVariance)
            {
                return thisType.CanCastToNonVariantInterface(otherType,protect);
            }
            else
            {
                if (thisType.CanCastByVarianceToInterfaceOrDelegate(otherType, protect))
                {
                    return true;
                }

                foreach (var interfaceType in thisType.RuntimeInterfaces)
                {
                    if (interfaceType.CanCastByVarianceToInterfaceOrDelegate(otherType, protect))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Example #9
0
        private static bool IsBoxedAndCanCastTo(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            TypeDesc fromUnderlyingType = thisType.UnderlyingType;

            if (fromUnderlyingType.IsGCPointer)
            {
                return(thisType.CanCastToInternal(otherType, protect));
            }
            else if (thisType.IsGenericParameter)
            {
                var genericVariableFromParam = (GenericParameterDesc)thisType;
                if (genericVariableFromParam.HasReferenceTypeConstraint)
                {
                    return(genericVariableFromParam.CanCastToInternal(otherType, protect));
                }
            }

            return(false);
        }
Example #10
0
        private static bool CanCastByVarianceToInterfaceOrDelegate(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protectInput)
        {
            if (!thisType.HasSameTypeDefinition(otherType))
            {
                return(false);
            }

            var stackOverflowProtectKey = new CastingPair(thisType, otherType);

            if (protectInput != null)
            {
                if (protectInput.Contains(stackOverflowProtectKey))
                {
                    return(false);
                }
            }

            StackOverflowProtect protect = new StackOverflowProtect(stackOverflowProtectKey, protectInput);

            Instantiation instantiationThis   = thisType.Instantiation;
            Instantiation instantiationTarget = otherType.Instantiation;
            Instantiation instantiationOpen   = thisType.GetTypeDefinition().Instantiation;

            Debug.Assert(instantiationThis.Length == instantiationTarget.Length &&
                         instantiationThis.Length == instantiationOpen.Length);

            for (int i = 0; i < instantiationThis.Length; i++)
            {
                TypeDesc arg       = instantiationThis[i];
                TypeDesc targetArg = instantiationTarget[i];

                if (arg != targetArg)
                {
                    GenericParameterDesc openArgType = (GenericParameterDesc)instantiationOpen[i];

                    switch (openArgType.Variance)
                    {
                    case GenericVariance.Covariant:
                        if (!arg.IsBoxedAndCanCastTo(targetArg, protect))
                        {
                            return(false);
                        }
                        break;

                    case GenericVariance.Contravariant:
                        if (!targetArg.IsBoxedAndCanCastTo(arg, protect))
                        {
                            return(false);
                        }
                        break;

                    default:
                        // non-variant
                        Debug.Assert(openArgType.Variance == GenericVariance.None);
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #11
0
 public StackOverflowProtect(CastingPair value, StackOverflowProtect previous)
 {
     _value = value;
     _previous = previous;
 }
Example #12
0
        private static bool IsBoxedAndCanCastTo(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            TypeDesc fromUnderlyingType = thisType.UnderlyingType;

            if (fromUnderlyingType.IsGCPointer)
            {
                return thisType.CanCastToInternal(otherType, protect);
            }
            else if (thisType.IsGenericParameter)
            {
                var genericVariableFromParam = (GenericParameterDesc)thisType;
                if (genericVariableFromParam.HasReferenceTypeConstraint)
                {
                    return genericVariableFromParam.CanCastToInternal(otherType, protect);
                }
            }

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

            // 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;
        }
Example #14
0
        private static bool CanCastByVarianceToInterfaceOrDelegate(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protectInput)
        {
            if (!thisType.HasSameTypeDefinition(otherType))
            {
                return false;
            }

            var stackOverflowProtectKey = new CastingPair(thisType, otherType);
            if (protectInput != null)
            {
                if (protectInput.Contains(stackOverflowProtectKey))
                    return false;
            }

            StackOverflowProtect protect = new StackOverflowProtect(stackOverflowProtectKey, protectInput);

            Instantiation instantiationThis = thisType.Instantiation;
            Instantiation instantiationTarget = otherType.Instantiation;
            Instantiation instantiationOpen = thisType.GetTypeDefinition().Instantiation;

            Debug.Assert(instantiationThis.Length == instantiationTarget.Length &&
                instantiationThis.Length == instantiationOpen.Length);

            for (int i = 0; i < instantiationThis.Length; i++)
            {
                TypeDesc arg = instantiationThis[i];
                TypeDesc targetArg = instantiationTarget[i];
                
                if (arg != targetArg)
                {
                    GenericParameterDesc openArgType = (GenericParameterDesc)instantiationOpen[i];

                    switch (openArgType.Variance)
                    {
                        case GenericVariance.Covariant:
                            if (!arg.IsBoxedAndCanCastTo(targetArg, protect))
                                return false;
                            break;

                        case GenericVariance.Contravariant:
                            if (!targetArg.IsBoxedAndCanCastTo(arg, protect))
                                return false;
                            break;

                        default:
                            // non-variant
                            Debug.Assert(openArgType.Variance == GenericVariance.None);
                            return false;
                    }
                }
            }

            return true;
        }
Example #15
0
        private static bool CanCastToNonVariantInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (otherType == thisType)
            {
                return true;
            }

            foreach (var interfaceType in thisType.RuntimeInterfaces)
            {
                if (interfaceType == otherType)
                {
                    return true;
                }
            }

            return false;
        }
Example #16
0
        private static bool CanCastToInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (!otherType.HasVariance)
            {
                return(thisType.CanCastToNonVariantInterface(otherType, protect));
            }
            else
            {
                if (thisType.CanCastByVarianceToInterfaceOrDelegate(otherType, protect))
                {
                    return(true);
                }

                foreach (var interfaceType in thisType.RuntimeInterfaces)
                {
                    if (interfaceType.CanCastByVarianceToInterfaceOrDelegate(otherType, protect))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #17
0
        private static bool CanCastToNonVariantInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (otherType == thisType)
            {
                return(true);
            }

            foreach (var interfaceType in thisType.RuntimeInterfaces)
            {
                if (interfaceType == otherType)
                {
                    return(true);
                }
            }

            return(false);
        }
Example #18
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 (toParamUnderlyingType.IsPrimitive)
                {
                    if (toParamUnderlyingType == fromParamUnderlyingType)
                    {
                        return true;
                    }

                    if (ArePrimitveTypesEquivalentSize(fromParamUnderlyingType, toParamUnderlyingType))
                    {
                        return true;
                    }
                }
            }

            // Anything else is not a match
            return false;
        }
Example #19
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);
        }
Example #20
0
        private static bool CanCastToInternal(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
        {
            if (thisType == otherType)
            {
                return(true);
            }

            switch (thisType.Category)
            {
            case TypeFlags.GenericParameter:
                return(((GenericParameterDesc)thisType).CanCastGenericParameterTo(otherType, protect));

            case TypeFlags.Array:
            case TypeFlags.SzArray:
                return(((ArrayType)thisType).CanCastArrayTo(otherType, protect));

            default:
                Debug.Assert(thisType.IsDefType);
                return(thisType.CanCastToClassOrInterface(otherType, protect));
            }
        }
Example #21
0
 public StackOverflowProtect(CastingPair value, StackOverflowProtect previous)
 {
     _value    = value;
     _previous = previous;
 }
Example #22
0
 private static bool CanCastToClassOrInterface(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect)
 {
     if (otherType.IsInterface)
     {
         return thisType.CanCastToInterface(otherType, protect);
     }
     else
     {
         return thisType.CanCastToClass(otherType, protect);
     }
 }