bool IsAssignable(TypeDesc src, TypeDesc dst, bool allowSizeEquivalence = false)
        {
            if (src == dst)
            {
                return(true);
            }

            if (src.IsValueType || dst.IsValueType)
            {
                if (allowSizeEquivalence && IsSameReducedType(src, dst))
                {
                    return(true);
                }

                // TODO IsEquivalent
                return(false);
            }

            return(CastingHelper.CanCastTo(src, dst));
        }
        bool IsAssignable(StackValue src, StackValue dst)
        {
            if (src.Kind == dst.Kind && src.Type == dst.Type)
            {
                return(true);
            }

            if (dst.Type == null)
            {
                return(false);
            }

            switch (src.Kind)
            {
            case StackValueKind.ObjRef:
                if (dst.Kind != StackValueKind.ObjRef)
                {
                    return(false);
                }

                // null is always assignable
                if (src.Type == null)
                {
                    return(true);
                }

                return(CastingHelper.CanCastTo(src.Type, dst.Type));

            case StackValueKind.ValueType:

                // TODO: Other cases - variance, etc.

                return(false);

            case StackValueKind.ByRef:

                // TODO: Other cases - variance, etc.

                return(false);

            case StackValueKind.Int32:
                return(dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);

            case StackValueKind.Int64:
                return(false);

            case StackValueKind.NativeInt:
                return(dst.Kind == StackValueKind.Int64);

            case StackValueKind.Float:
                return(false);

            default:
                // TODO:
                // return false;
                throw new NotImplementedException();
            }

#if false
            if (child == parent)
            {
                return(TRUE);
            }

            // Normally we just let the runtime sort it out but we wish to be more strict
            // than the runtime wants to be.  For backwards compatibility, the runtime considers
            // int32[] and nativeInt[] to be the same on 32-bit machines.  It also is OK with
            // int64[] and nativeInt[] on a 64-bit machine.

            if (child.IsType(TI_REF) && parent.IsType(TI_REF) &&
                jitInfo->isSDArray(child.GetClassHandleForObjRef()) &&
                jitInfo->isSDArray(parent.GetClassHandleForObjRef()))
            {
                BOOL runtime_OK;

                // never be more lenient than the runtime
                runtime_OK = jitInfo->canCast(child.m_cls, parent.m_cls);
                if (!runtime_OK)
                {
                    return(false);
                }

                CORINFO_CLASS_HANDLE handle;
                CorInfoType          pType = jitInfo->getChildType(child.GetClassHandleForObjRef(), &handle);
                CorInfoType          cType = jitInfo->getChildType(parent.GetClassHandleForObjRef(), &handle);

                // don't care whether it is signed
                if (cType == CORINFO_TYPE_NATIVEUINT)
                {
                    cType = CORINFO_TYPE_NATIVEINT;
                }
                if (pType == CORINFO_TYPE_NATIVEUINT)
                {
                    pType = CORINFO_TYPE_NATIVEINT;
                }

                if (cType == CORINFO_TYPE_NATIVEINT)
                {
                    return(pType == CORINFO_TYPE_NATIVEINT);
                }

                if (pType == CORINFO_TYPE_NATIVEINT)
                {
                    return(cType == CORINFO_TYPE_NATIVEINT);
                }

                return(runtime_OK);
            }

            if (parent.IsUnboxedGenericTypeVar() || child.IsUnboxedGenericTypeVar())
            {
                return(FALSE); // need to have had child == parent
            }
            else if (parent.IsType(TI_REF))
            {
                // An uninitialized objRef is not compatible to initialized.
                if (child.IsUninitialisedObjRef() && !parent.IsUninitialisedObjRef())
                {
                    return(FALSE);
                }

                if (child.IsNullObjRef())           // NULL can be any reference type
                {
                    return(TRUE);
                }
                if (!child.IsType(TI_REF))
                {
                    return(FALSE);
                }

                return(jitInfo->canCast(child.m_cls, parent.m_cls));
            }
            else if (parent.IsType(TI_METHOD))
            {
                if (!child.IsType(TI_METHOD))
                {
                    return(FALSE);
                }

                // Right now we don't bother merging method handles
                return(FALSE);
            }
            else if (parent.IsType(TI_STRUCT))
            {
                if (!child.IsType(TI_STRUCT))
                {
                    return(FALSE);
                }

                // Structures are compatible if they are equivalent
                return(jitInfo->areTypesEquivalent(child.m_cls, parent.m_cls));
            }
            else if (parent.IsByRef())
            {
                return(tiCompatibleWithByRef(jitInfo, child, parent));
            }

            return(FALSE);
#endif
        }