Repository: JuliaLang/julia
File: Compiler/src/typeutils.jl (Julia)

Code before:
    na = length(argtypes)
    groups = compute_alias_groups(na, fargs, argtypes)
    return _switchtupleunion(𝕃, argtypes, na, [], nothing, groups)
end

function _switchtupleunion(𝕃::AbstractLattice, t::Vector{Any}, i::Int, tunion::Vector{Any},
                           @nospecialize(origt), groups::Union{Nothing,Vector{Int}}=nothing)
    if i == 0
        if origt === nothing
            push!(tunion, copy(t))
        else
            tpl = rewrap_unionall(Tuple{t...}, origt)
            push!(tunion, tpl)
        end
        return tunion
    end

    if groups !== nothing && groups[i] != i
        # If this position is a follower (aliased to an earlier position),
        # its type is already set by the leader — just recurse without iterating.
        _switchtupleunion(𝕃, t, i - 1, tunion, origt, groups)
    else
        origti = ti = t[i]
        followers = Int[]
        if groups !== nothing
            for j in i+1:length(t)
                if groups[j] == i # Collect follower indices for this leader
                    push!(followers, j)
                end
            end
        end
        # TODO Generalize this to allow callsite union-splitting of MustAlias
        if isa(ti, Union)
            origtypes = Any[t[j] for j in followers]
            for ty in uniontypes(ti)
                t[i] = ty
                for j in followers
                    t[j] = ty
                end
                _switchtupleunion(𝕃, t, i - 1, tunion, origt, groups)
            end
            t[i] = origti
            for (k, j) in enumerate(followers)
                t[j] = origtypes[k]
            end
        elseif (has_extended_unionsplit(𝕃) && !isa(ti, Const) && !isvarargtype(ti) &&
            (wty = widenconst(ti); isa(wty, Union)))
            origtypes = Any[t[j] for j in followers]
            for ty in uniontypes(wty)
                t[i] = ty
                for j in followers

Review comment (suggestion):
nit: The implementation right now constrains that `i > j`, but nothing really says that it must be true>
```suggestion
            for j in 1:length(t)
```

Additionally, when we have alias groups, it might be cool to similarly refine dependent types during `smerge!` also

Code after:
    na = length(argtypes)
    groups = compute_alias_groups(na, fargs, argtypes)
    return _switchtupleunion(𝕃, argtypes, na, [], nothing, groups)
end

function _switchtupleunion(𝕃::AbstractLattice, t::Vector{Any}, i::Int, tunion::Vector{Any},
                           @nospecialize(origt), groups::Union{Nothing,Vector{Int}}=nothing)
    if i == 0
        if origt === nothing
            push!(tunion, copy(t))
        else
            tpl = rewrap_unionall(Tuple{t...}, origt)
            push!(tunion, tpl)
        end
        return tunion
    end

    if groups !== nothing && groups[i] != i
        # If this position is a follower (aliased to an earlier position),
        # its type is already set by the leader — just recurse without iterating.
        _switchtupleunion(𝕃, t, i - 1, tunion, origt, groups)
    else
        origti = ti = t[i]
        followers = Int[]
        if groups !== nothing
            for j in 1:length(t)
                if groups[j] == i # Collect follower indices for this leader
                    push!(followers, j)
                end
            end
        end
        # TODO Generalize this to allow callsite union-splitting of MustAlias
        if isa(ti, Union)
            origtypes = Any[t[j] for j in followers]
            for ty in uniontypes(ti)
                t[i] = ty
                for j in followers
                    t[j] = ty
                end
                _switchtupleunion(𝕃, t, i - 1, tunion, origt, groups)
            end
            t[i] = origti
            for (k, j) in enumerate(followers)
                t[j] = origtypes[k]
            end
        elseif (has_extended_unionsplit(𝕃) && !isa(ti, Const) && !isvarargtype(ti) &&
            (wty = widenconst(ti); isa(wty, Union)))
            origtypes = Any[t[j] for j in followers]
            for ty in uniontypes(wty)
                t[i] = ty
                for j in followers