Skip to content

Commit

Permalink
make printing of typealias env shorter
Browse files Browse the repository at this point in the history
Inspired by #35710

Co-authored-by: Stephan Hilb <[email protected]>
  • Loading branch information
vtjnash and stev47 committed Mar 18, 2021
1 parent ae0dc54 commit 3555c32
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 43 deletions.
98 changes: 70 additions & 28 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,56 @@ function make_typealias(@nospecialize(x::Type))
end
end

function show_can_elide(p::TypeVar, wheres::Vector, elide::Int, env::SimpleVector, skip::Int)
elide == 0 && return false
wheres[elide] === p || return false
for i = (elide + 1):length(wheres)
v = wheres[i]::TypeVar
has_typevar(v.lb, p) && return false
has_typevar(v.ub, p) && return false
end
for i = 1:length(env)
i == skip && continue
has_typevar(env[i], p) && return false
end
return true
end

function show_typeparams(io::IO, env::SimpleVector, wheres::Vector)
n = length(env)
print(io, "{")
elide = length(wheres)
for i = n:-1:1
p = env[i]
if p isa TypeVar
if p.lb === Union{} && show_can_elide(p, wheres, elide, env, i)
elide -= 1
elseif p.ub === Any && show_can_elide(p, wheres, elide, env, i)
elide -= 1
end
end
end
for i = 1:n
p = env[i]
if p isa TypeVar
if p.lb === Union{} && something(findfirst(w -> w === p, wheres), 0) > elide
print(io, "<:")
show(io, p.ub)
elseif p.ub === Any && something(findfirst(w -> w === p, wheres), 0) > elide
print(io, ">:")
show(io, p.lb)
else
show(io, p)
end
else
show(io, p)
end
i < n && print(io, ", ")
end
print(io, "}")
return elide
end

function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, wheres::Vector)
if !(get(io, :compact, false)::Bool)
# Print module prefix unless alias is visible from module passed to
Expand All @@ -595,21 +645,14 @@ function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, whe
end
end
print(io, name.name)
n = length(env)
n == 0 && return

print(io, "{")
param_io = IOContext(io)
for i = 1:length(wheres)
p = wheres[i]::TypeVar
param_io = IOContext(param_io, :unionall_env => p)
end
for i = 1:n
p = env[i]
show(param_io, p)
i < n && print(io, ", ")
isempty(env) && return
io = IOContext(io)
for p in wheres
io = IOContext(io, :unionall_env => p)
end
print(io, "}")
elide = show_typeparams(io, env, wheres)
resize!(wheres, elide)
nothing
end

function make_wheres(io::IO, env::SimpleVector, @nospecialize(x::Type))
Expand Down Expand Up @@ -642,12 +685,12 @@ function make_wheres(io::IO, env::SimpleVector, @nospecialize(x::Type))
return wheres
end

function show_wheres(io::IO, env::Vector)
isempty(env) && return
function show_wheres(io::IO, wheres::Vector)
isempty(wheres) && return
io = IOContext(io)
n = length(env)
n = length(wheres)
for i = 1:n
p = env[i]::TypeVar
p = wheres[i]::TypeVar
print(io, n == 1 ? " where " : i == 1 ? " where {" : ", ")
show(io, p)
io = IOContext(io, :unionall_env => p)
Expand Down Expand Up @@ -857,7 +900,11 @@ function _show_type(io::IO, @nospecialize(x::Type))
push!(wheres, var)
io = IOContext(io, :unionall_env => var)
end
show(io, x)
if x isa DataType
show_datatype(io, x, wheres)
else
show(io, x)
end
end
show_wheres(io, wheres)
end
Expand Down Expand Up @@ -919,13 +966,13 @@ function show_type_name(io::IO, tn::Core.TypeName)
nothing
end

function show_datatype(io::IO, @nospecialize(x::DataType))
function show_datatype(io::IO, @nospecialize(x::DataType), wheres::Vector=TypeVar[])
parameters = x.parameters::SimpleVector
istuple = x.name === Tuple.name
n = length(parameters)

# Print homogeneous tuples with more than 3 elements compactly as NTuple{N, T}
if istuple && n > 3 && all(i -> (parameters[1] === i), parameters)
if istuple && n > 3 && all(@nospecialize(i) -> (parameters[1] === i), parameters)
print(io, "NTuple{", n, ", ", parameters[1], "}")
else
show_type_name(io, x.name)
Expand All @@ -934,13 +981,8 @@ function show_datatype(io::IO, @nospecialize(x::DataType))
# printing a method signature or type parameter.
# Always print the type parameter if we are printing the type directly
# since this information is still useful.
print(io, '{')
for i = 1:n
p = parameters[i]
show(io, p)
i < n && print(io, ", ")
end
print(io, '}')
elide = show_typeparams(io, parameters, wheres)
resize!(wheres, elide)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ consider the two types created by the following declarations:

```jldoctest
julia> const T1 = Array{Array{T,1} where T, 1}
Vector{Vector{T} where T} (alias for Array{Array{T, 1} where T, 1})
Vector{Vector{<:Any}} (alias for Array{Array{T, 1} where T, 1})
julia> const T2 = Array{Array{T, 1}, 1} where T
Array{Vector{T}, 1} where T
Expand Down
2 changes: 1 addition & 1 deletion stdlib/InteractiveUtils/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ end
Base.getindex(A::Stable, i) = A.A[i]
Base.getindex(A::Unstable, i) = A.A[i]

tag = "ARRAY{FLOAT64, N}"
tag = "ARRAY{FLOAT64, <:ANY}"
@test warntype_hastag(getindex, Tuple{Unstable{Float64},Int}, tag)
@test !warntype_hastag(getindex, Tuple{Stable{Float64,2},Int}, tag)
@test warntype_hastag(getindex, Tuple{Stable{Float64},Int}, tag)
Expand Down
2 changes: 1 addition & 1 deletion test/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ let err_str,
@test startswith(sprint(show, which(FunctionLike(), Tuple{})),
"(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)")
@test startswith(sprint(show, which(StructWithUnionAllMethodDefs{<:Integer}, (Any,))),
"($(curmod_prefix)StructWithUnionAllMethodDefs{T} where T<:Integer)(x)")
"($(curmod_prefix)StructWithUnionAllMethodDefs{<:Integer})(x)")
@test repr("text/plain", FunctionLike()) == "(::$(curmod_prefix)FunctionLike) (generic function with 1 method)"
@test repr("text/plain", Core.arraysize) == "arraysize (built-in function)"

Expand Down
2 changes: 1 addition & 1 deletion test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ let ex = :(a + b)
end
foo13825(::Array{T, N}, ::Array, ::Vector) where {T, N} = nothing
@test startswith(string(first(methods(foo13825))),
"foo13825(::Array{T, N}, ::Array, ::Vector{T} where T)")
"foo13825(::Array{T, N}, ::Array, ::Vector{<:Any}) where {T, N} in")

mutable struct TLayout
x::Int8
Expand Down
76 changes: 65 additions & 11 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1569,12 +1569,64 @@ end
end

let x = TypeVar(:_), y = TypeVar(:_)
@test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{_1, _2} where {_1, _2}"
@test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{_1} where _1, _1} where _1"
@test repr(UnionAll(x, UnionAll(y, Pair{x,y}))) == "Pair{<:Any, <:Any}"
@test repr(UnionAll(y, UnionAll(x, Pair{x,y}))) == "Pair{<:Any, _1} where _1"
@test repr(UnionAll(x, UnionAll(y, Pair{UnionAll(x,Ref{x}),y}))) == "Pair{Ref{<:Any}, <:Any}"
@test repr(UnionAll(y, UnionAll(x, Pair{UnionAll(y,Ref{x}),y}))) == "Pair{Ref{_2}, _1} where {_1, _2}"
x = TypeVar(:a)
y = TypeVar(:a)
z = TypeVar(:a)
@test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{a1, a2, a} where {a, a1, a2}"
@test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z})))) == "Tuple{<:Any, <:Any, a} where a"
@test repr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{z,y,x})))) == "Tuple{a, <:Any, a1} where {a, a1}"
end

is_juliarepr(x) = eval(Meta.parse(repr(x))) == x
@testset "unionall types" begin
X = TypeVar(gensym())
Y = TypeVar(gensym(), Ref, Ref)
x, y, z = TypeVar(:a), TypeVar(:a), TypeVar(:a)
struct TestTVUpper{A<:Integer} end

# named typevars
@test is_juliarepr(Ref{A} where A)
@test is_juliarepr(Ref{A} where A>:Ref)
@test is_juliarepr(Ref{A} where A<:Ref)
@test is_juliarepr(Ref{A} where Ref<:A<:Ref)
@test is_juliarepr(TestTVUpper{<:Real})
@test is_juliarepr(TestTVUpper{<:Integer})
@test is_juliarepr(TestTVUpper{<:Signed})

# typearg order
@test is_juliarepr(UnionAll(X, Pair{X,<:Any}))
@test is_juliarepr(UnionAll(X, Pair{<:Any,X}))

# duplicates
@test is_juliarepr(UnionAll(X, Pair{X,X}))

# nesting
@test is_juliarepr(UnionAll(X, Ref{Ref{X}}))
@test is_juliarepr(Union{T, Int} where T)
@test is_juliarepr(Pair{A, <:A} where A)

# renumbered typevars with same names
@test is_juliarepr(UnionAll(z, UnionAll(x, UnionAll(y, Tuple{x,y,z}))))

# shortened typevar printing
@test repr(Ref{<:Any}) == "Ref{<:Any}" # improve?
@test repr(Pair{1, <:Any}) == "Pair{1, <:Any}" # improve?
@test repr(Ref{<:Ref}) == "Ref{<:Ref}"
@test repr(Ref{>:Ref}) == "Ref{>:Ref}"
@test repr(Pair{<:Any, 1}) == "Pair{<:Any, 1}"
yname = sprint(Base.show_unquoted, Y.name)
@test repr(UnionAll(Y, Ref{Y})) == "Ref{$yname} where Ref<:$yname<:Ref"
@test endswith(repr(TestTVUpper{<:Real}), "TestTVUpper{<:Real}")
@test endswith(repr(TestTVUpper{<:Integer}), "TestTVUpper{<:Integer}") # improve?
@test endswith(repr(TestTVUpper{<:Signed}), "TestTVUpper{<:Signed}")

# exception for tuples
@test is_juliarepr(Tuple)
@test is_juliarepr(Tuple{})
@test is_juliarepr(Tuple{<:Any})
end

@testset "showarg" begin
Expand Down Expand Up @@ -1659,7 +1711,7 @@ end
@test showstr([Float16(1)]) == "Float16[1.0]"
@test showstr([[Float16(1)]]) == "Vector{Float16}[[1.0]]"
@test replstr(Real[Float16(1)]) == "1-element Vector{Real}:\n Float16(1.0)"
@test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real, N} where N}:\n [1]"
@test replstr(Array{Real}[Real[1]]) == "1-element Vector{Array{Real, <:Any}}:\n [1]"
# printing tuples (Issue #25042)
@test replstr(fill((Int64(1), zeros(Float16, 3)), 1)) ==
"1-element Vector{Tuple{Int64, Vector{Float16}}}:\n (1, [0.0, 0.0, 0.0])"
Expand Down Expand Up @@ -1706,9 +1758,9 @@ end
@test replstr([[1.0]=>1.0]) == "1-element Vector{Pair{Vector{Float64}, Float64}}:\n [1.0] => 1.0"

# issue #28159
@test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{names, Tuple{$Int, $Int}} where names}:\n (a = 1, b = 2)\n (a = 3, c = 4)"
@test replstr([(a=1, b=2), (a=3,c=4)]) == "2-element Vector{NamedTuple{<:Any, Tuple{$Int, $Int}}}:\n (a = 1, b = 2)\n (a = 3, c = 4)"

@test replstr(Vector[Any[1]]) == "1-element Vector{Vector{T} where T}:\n Any[1]"
@test replstr(Vector[Any[1]]) == "1-element Vector{Vector{<:Any}}:\n Any[1]"
@test replstr(AbstractDict{Integer,Integer}[Dict{Integer,Integer}(1=>2)]) ==
"1-element Vector{AbstractDict{Integer, Integer}}:\n Dict(1 => 2)"

Expand Down Expand Up @@ -1929,7 +1981,7 @@ end

@testset """printing "Any" is not skipped with nested arrays""" begin
@test replstr(Union{X28004,Vector}[X28004(Any[X28004(1)])], :compact => true) ==
"1-element Vector{Union{X28004, Vector{T} where T}}:\n X(Any[X(1)])"
"1-element Vector{Union{X28004, Vector{<:Any}}}:\n X(Any[X(1)])"
end

# Issue 25589 - Underlines in cmd printing
Expand Down Expand Up @@ -2096,11 +2148,13 @@ end
@test Base.make_typealias(M37012.AStruct{1}) === nothing
@test isempty(Base.make_typealiases(M37012.AStruct{1})[1])
@test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}"
@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{T} where T}"
@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{T} where T}"
@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{<:Any}}"
@test string(Union{Nothing, Number, Vector{<:Integer}}) == "Union{Nothing, Number, Vector{<:Integer}}"
@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{<:Any}}"
@test string(Union{Nothing, AbstractVecOrMat{<:Integer}}) == "Union{Nothing, AbstractVecOrMat{<:Integer}}"
@test string(M37012.BStruct{T, T} where T) == "$(curmod_prefix)M37012.B2{T, T} where T"
@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Unsigned, S<:Signed}"
@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Signed, S<:T}"
@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{<:Signed, T} where T<:Unsigned"
@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{<:T, T} where T<:Signed"
@test string(Union{M37012.SimpleU, Nothing}) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU}"
@test string(Union{M37012.SimpleU, Nothing, T} where T) == "Union{Nothing, $(curmod_prefix)M37012.SimpleU, T} where T"
@test string(Union{AbstractVector{T}, T} where T) == "Union{AbstractVector{T}, T} where T"
Expand Down

0 comments on commit 3555c32

Please sign in to comment.