Repository: JuliaLang/julia
File: stdlib/InteractiveUtils/src/macros.jl (Julia)

Code before:
typesof_expr_unescaped(args::Vector{Any}, where_params::Union{Nothing, Vector{Any}} = nothing) = rewrap_where(:($make_tuple_type(Any[$(Any[reescape(get_typeof, a) for a in args]...)])), where_params)

function make_tuple_type(types::Vector{Any})
    vararg = -1
    for i in eachindex(types)
        i == 1 && continue # ignore function type
        type = types[i]
        if isa(type, Core.TypeofVararg)
            vararg !== -1 && throw(ArgumentError("More than one `Core.Vararg` type present in argument tuple ($type detected after $(types[vararg])); if provided, it must be unique"))
            vararg = i
            if isdefined(type, :N)
                n = length(types) - vararg + 1
                n > type.N && throw(ArgumentError("Expected at most $(type.N) types after `$type`, found $n instead"))
            end
        elseif vararg !== -1
            ref = types[vararg]
            if isdefined(ref, :T) && !skip_type_check(ref.T) && !skip_type_check(type)
                !(type <: ref.T) && throw(ArgumentError("Inconsistent type `$type` detected after `$ref`; `$type <: $(ref.T)` must hold"))
            end
        end
    end
    vararg === -1 && return Tuple{types...}
    return Tuple{@view(types[1:vararg])...}
end

skip_type_check(@nospecialize(T)) = isa(T, TypeVar) || Core.has_free_typevars(T)

function extract_where_parameters(ex::Expr)
    isexpr(ex, :where) || return ex, nothing
    ex.args[1], ex.args[2:end]
end

function rewrap_where(ex::Expr, where_params::Union{Nothing, Vector{Any}})
    isnothing(where_params) && return ex
    Expr(:where, ex, esc.(where_params)...)
end

function reescape(f::Function, @nospecialize ex)
    isa(ex, Expr) || return f(ex)
    unescaped = Meta.unescape(ex)
    new = f(unescaped)
    return Meta.reescape(new, ex)
end

get_typeof(ex::Ref) = ex[]
function get_typeof(@nospecialize ex)
    isexpr(ex, :(::), 1) && return ex.args[1]
    isexpr(ex, :(::), 2) && return ex.args[2]
    if isexpr(ex, :..., 1)
        splatted = ex.args[1]
        isexpr(splatted, :(::)) && return Expr(:curly, :(Core.Vararg), splatted.args[end])

Review comment (suggestion):
```suggestion
skip_type_check(@nospecialize(T)) = Core.has_free_typevars(T)
```

I believe this case is already covered for you:
```julia
julia> Core.has_free_typevars(Core.TypeVar(:X))
true
```

Code after:
typesof_expr_unescaped(args::Vector{Any}, where_params::Union{Nothing, Vector{Any}} = nothing) = rewrap_where(:($make_tuple_type(Any[$(Any[reescape(get_typeof, a) for a in args]...)])), where_params)

function make_tuple_type(types::Vector{Any})
    vararg = -1
    for i in eachindex(types)
        i == 1 && continue # ignore function type
        type = types[i]
        if isa(type, Core.TypeofVararg)
            vararg !== -1 && throw(ArgumentError("More than one `Core.Vararg` type present in argument tuple ($type detected after $(types[vararg])); if provided, it must be unique"))
            vararg = i
            if isdefined(type, :N)
                n = length(types) - vararg + 1
                n > type.N && throw(ArgumentError("Expected at most $(type.N) types after `$type`, found $n instead"))
            end
        elseif vararg !== -1
            ref = types[vararg]
            if isdefined(ref, :T) && !skip_type_check(ref.T) && !skip_type_check(type)
                !(type <: ref.T) && throw(ArgumentError("Inconsistent type `$type` detected after `$ref`; `$type <: $(ref.T)` must hold"))
            end
        end
    end
    vararg === -1 && return Tuple{types...}
    return Tuple{@view(types[1:vararg])...}
end

skip_type_check(@nospecialize(T)) = Core.has_free_typevars(T)

function extract_where_parameters(ex::Expr)
    isexpr(ex, :where) || return ex, nothing
    ex.args[1], ex.args[2:end]
end

function rewrap_where(ex::Expr, where_params::Union{Nothing, Vector{Any}})
    isnothing(where_params) && return ex
    Expr(:where, ex, esc.(where_params)...)
end

function reescape(f::Function, @nospecialize ex)
    isa(ex, Expr) || return f(ex)
    unescaped = Meta.unescape(ex)
    new = f(unescaped)
    return Meta.reescape(new, ex)
end

get_typeof(ex::Ref) = ex[]
function get_typeof(@nospecialize ex)
    isexpr(ex, :(::), 1) && return ex.args[1]
    isexpr(ex, :(::), 2) && return ex.args[2]
    if isexpr(ex, :..., 1)
        splatted = ex.args[1]
        isexpr(splatted, :(::)) && return Expr(:curly, :(Core.Vararg), splatted.args[end])