need_type_where(
	type_T	*actual,
	type_T	*expected,
	int	offset,
	where_T	where,
	cctx_T	*cctx,
	int	silent,
	int	actual_is_const)
{
    int ret;

    if (expected == &t_bool && actual != &t_bool
					&& (actual->tt_flags & TTFLAG_BOOL_OK))
    {
	// Using "0", "1" or the result of an expression with "&&" or "||" as a
	// boolean is OK but requires a conversion.
	generate_2BOOL(cctx, FALSE, offset);
	return OK;
    }

    ret = check_type_maybe(expected, actual, FALSE, where);
    if (ret == OK)
	return OK;

    // If the actual type can be the expected type add a runtime check.
    // If it's a constant a runtime check makes no sense.
    if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected))
    {
	generate_TYPECHECK(cctx, expected, offset, where.wt_index);
	return OK;
    }

    if (!silent)
	type_mismatch_where(expected, actual, where);
    return FAIL;
}
need_type_where(
	type_T	*actual,
	type_T	*expected,
	int	offset,
	where_T	where,
	cctx_T	*cctx,
	int	silent,
	int	actual_is_const)
{
    int ret;

    if (expected == &t_bool && actual != &t_bool
					&& (actual->tt_flags & TTFLAG_BOOL_OK))
    {
	 
	 
	generate_2BOOL(cctx, FALSE, offset);
	return OK;
    }

    ret = check_type_maybe(expected, actual, FALSE, where);
    if (ret == OK)
	return OK;

     
     
    if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected))
    {
	generate_TYPECHECK(cctx, expected, offset, where.wt_index);
	return OK;
    }

    if (!silent)
	type_mismatch_where(expected, actual, where);
    return FAIL;
}