def is_castable(src, dst):
    """
    Check if src type can be cast to dst type
    """
    if ((src in [int, bool]) or rdltypes.is_user_enum(src)) and (dst in [int, bool]):
        # Pure numeric or enum can be cast to a numeric
        return True
    elif (src == rdltypes.ArrayPlaceholder) and (dst == rdltypes.ArrayPlaceholder):
        # Check that array element types also match
        if src.element_type is None:
            # indeterminate array type. Is castable
            return True
        elif src.element_type == dst.element_type:
            return True
        else:
            return False
    elif rdltypes.is_user_struct(dst):
        # Structs can be assigned their derived counterparts - aka their subclasses
        return issubclass(src, dst)
    elif dst == rdltypes.PropertyReference:
        return issubclass(src, rdltypes.PropertyReference)
    elif src == dst:
        return True
    else:
        return False
Check if src type can be cast to dst type