Repository: JuliaLang/julia
File: src/subtype.c (C)

Code before:
        jl_value_t *a = widen_Type_if_concrete(((jl_uniontype_t*)t)->a);
        jl_value_t *b = widen_Type_if_concrete(((jl_uniontype_t*)t)->b);
        if (a == b)
            return a;
    }
    if (jl_is_unionall(t)) {
        jl_unionall_t *u = (jl_unionall_t*)t;
        jl_value_t *body = widen_Type_if_concrete(u->body);
        if (body != u->body && !jl_has_typevar(body, u->var))
            return body;
    }
    return t;
}

static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e);

// Map Type{X} to kind type (DataType, UnionAll, Union, TypeofBottom) over union
// drop members of the union where the widened kind doesn't satisfy `bound`
// sets `*filtered` to the union of original (non-widened) surviving members
static jl_value_t *widen_Type_to_union(jl_value_t *t, jl_value_t *bound, jl_stenv_t *e, jl_value_t **filtered)
{
    if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) {
        jl_value_t *w = jl_typeof(jl_tparam0(t));
        if (!try_subtype_in_env(w, bound, e)) {
            *filtered = jl_bottom_type;
            return jl_bottom_type;
        }
        *filtered = t;
        return w;
    }
    if (jl_is_uniontype(t)) {
        jl_value_t *wa = NULL, *wb = NULL, *fa = NULL, *fb = NULL;
        JL_GC_PUSH4(&wa, &wb, &fa, &fb);
        wa = widen_Type_to_union(((jl_uniontype_t*)t)->a, bound, e, &fa);
        wb = widen_Type_to_union(((jl_uniontype_t*)t)->b, bound, e, &fb);
        if (wa != ((jl_uniontype_t*)t)->a || wb != ((jl_uniontype_t*)t)->b) {
            *filtered = simple_join(fa, fb);
            fa = simple_join(wa, wb); // reuse root
        }
        else {
            *filtered = t;
            fa = t;
        }
        JL_GC_POP();
        return fa;
    }
    if (jl_is_unionall(t)) {
        jl_unionall_t *u = (jl_unionall_t*)t;
        jl_value_t *fbody = NULL, *body = NULL;
        JL_GC_PUSH2(&body, &fbody);
        body = widen_Type_to_union(u->body, bound, e, &fbody);

Review comment (suggestion):
I'm not sure return a `Union{}` is a good idea here, this might remove part of `ub` and make the result too narrow, e.g.
```julia
typeintersect(Tuple{Union{Type{Val},Type{Int8}},Union{Type{Val},Type{Int}}}, NTuple{2,<:Union{Type{<:Val},DataType}})
```
why not just return `t`?

BTW, there seems no need to maintain `filtered` if `widen_Type_to_union` only performs widening (and does no filtering). IIUC, it was added only for the branch in L2916, we could return ub there if ub2 is concrete.

Code after:
        jl_value_t *a = widen_Type_if_concrete(((jl_uniontype_t*)t)->a);
        jl_value_t *b = widen_Type_if_concrete(((jl_uniontype_t*)t)->b);
        if (a == b)
            return a;
    }
    if (jl_is_unionall(t)) {
        jl_unionall_t *u = (jl_unionall_t*)t;
        jl_value_t *body = widen_Type_if_concrete(u->body);
        if (body != u->body && !jl_has_typevar(body, u->var))
            return body;
    }
    return t;
}

static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e);

// Map Type{X} to kind type (DataType, UnionAll, Union, TypeofBottom) over union
// only if the widened kind satisfies `bound` , otherwise leave unchanged
static jl_value_t *widen_Type_to_union(jl_value_t *t, jl_value_t *bound, jl_stenv_t *e)
{
    if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) {
        jl_value_t *w = jl_typeof(jl_tparam0(t));
        if (!try_subtype_in_env(w, bound, e))
            return t;
        return w;
    }
    if (jl_is_uniontype(t)) {
        jl_value_t *wa = NULL, *wb = NULL;
        JL_GC_PUSH2(&wa, &wb);
        wa = widen_Type_to_union(((jl_uniontype_t*)t)->a, bound, e);
        wb = widen_Type_to_union(((jl_uniontype_t*)t)->b, bound, e);
        if (wa != ((jl_uniontype_t*)t)->a || wb != ((jl_uniontype_t*)t)->b)
            wa = simple_join(wa, wb);
        else
            wa = t;
        JL_GC_POP();
        return wa;
    }
    if (jl_is_unionall(t)) {
        jl_unionall_t *u = (jl_unionall_t*)t;
        jl_value_t *body = NULL;
        JL_GC_PUSH1(&body);
        body = widen_Type_to_union(u->body, bound, e);
        if (body != u->body && !jl_has_typevar(body, u->var)) {
            JL_GC_POP();
            return body;
        }
        JL_GC_POP();
    }
    return t;
}