Skip to content

Commit 52fbe7f

Browse files
vtjnashKristofferC
authored andcommitted
show: fix some bugs in typealias printing
(cherry picked from commit b6df6c2)
1 parent aeca6f1 commit 52fbe7f

File tree

2 files changed

+69
-22
lines changed

2 files changed

+69
-22
lines changed

base/show.jl

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,9 @@ function makeproper(io::IO, x::Type)
532532
push!(y, typ)
533533
end
534534
end
535-
normal || (x = Union{y...})
536-
properx = rewrap_unionall(x, properx)
535+
if !normal
536+
properx = rewrap_unionall(Union{y...}, properx)
537+
end
537538
end
538539
has_free_typevars(properx) && return Any
539540
return properx
@@ -580,8 +581,8 @@ function make_typealias(@nospecialize(x::Type))
580581
applied = rewrap_unionall(applied, p)
581582
end
582583
has_free_typevars(applied) && continue
583-
applied == x || continue # it couldn't figure out the parameter matching
584-
elseif alias <: x
584+
applied === x || continue # it couldn't figure out the parameter matching
585+
elseif alias === x
585586
env = Core.svec()
586587
else
587588
continue # not a complete match
@@ -596,7 +597,7 @@ function make_typealias(@nospecialize(x::Type))
596597
end
597598
end
598599

599-
function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector)
600+
function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector, wheres::Vector)
600601
if !(get(io, :compact, false)::Bool)
601602
# Print module prefix unless alias is visible from module passed to
602603
# IOContext. If :module is not set, default to Main. nothing can be used
@@ -612,34 +613,70 @@ function show_typealias(io::IO, name::GlobalRef, x::Type, env::SimpleVector)
612613
n == 0 && return
613614

614615
print(io, "{")
615-
let io = IOContext(io)
616-
for i = n:-1:1
617-
p = env[i]
618-
if p isa TypeVar
619-
io = IOContext(io, :unionall_env => p)
616+
param_io = IOContext(io)
617+
for i = 1:length(wheres)
618+
p = wheres[i]::TypeVar
619+
param_io = IOContext(param_io, :unionall_env => p)
620+
end
621+
for i = 1:n
622+
p = env[i]
623+
show(param_io, p)
624+
i < n && print(io, ", ")
625+
end
626+
print(io, "}")
627+
end
628+
629+
function make_wheres(io::IO, env::SimpleVector, @nospecialize(x::Type))
630+
seen = IdSet()
631+
wheres = []
632+
# record things printed by the context
633+
if io isa IOContext
634+
for (key, val) in io.dict
635+
if key === :unionall_env && val isa TypeVar && has_typevar(x, val)
636+
push!(seen, val)
620637
end
621638
end
622-
for i = 1:n
623-
p = env[i]
624-
show(io, p)
625-
i < n && print(io, ", ")
639+
end
640+
# record things in x to print outermost
641+
while x isa UnionAll
642+
if !(x.var in seen)
643+
push!(seen, x.var)
644+
push!(wheres, x.var)
626645
end
646+
x = x.body
627647
end
628-
print(io, "}")
629-
for i = n:-1:1
648+
# record remaining things in env to print innermost
649+
for i = length(env):-1:1
630650
p = env[i]
631-
if p isa TypeVar && !io_has_tvar_name(io, p.name, x)
632-
print(io, " where ")
633-
show(io, p)
651+
if p isa TypeVar && !(p in seen)
652+
push!(seen, p)
653+
pushfirst!(wheres, p)
634654
end
635655
end
656+
return wheres
657+
end
658+
659+
function show_wheres(io::IO, env::Vector)
660+
isempty(env) && return
661+
io = IOContext(io)
662+
n = length(env)
663+
for i = 1:n
664+
p = env[i]::TypeVar
665+
print(io, n == 1 ? " where " : i == 1 ? " where {" : ", ")
666+
show(io, p)
667+
io = IOContext(io, :unionall_env => p)
668+
end
669+
n > 1 && print(io, "}")
670+
nothing
636671
end
637672

638673
function show_typealias(io::IO, x::Type)
639674
properx = makeproper(io, x)
640675
alias = make_typealias(properx)
641676
alias === nothing && return false
642-
show_typealias(io, alias[1], x, alias[2])
677+
wheres = make_wheres(io, alias[2], x)
678+
show_typealias(io, alias[1], x, alias[2], wheres)
679+
show_wheres(io, wheres)
643680
return true
644681
end
645682

@@ -735,13 +772,17 @@ function show_unionaliases(io::IO, x::Union)
735772
end
736773
if first && length(aliases) == 1
737774
alias = aliases[1]
738-
show_typealias(io, alias[1], x, alias[2])
775+
wheres = make_wheres(io, alias[2], x)
776+
show_typealias(io, alias[1], x, alias[2], wheres)
777+
show_wheres(io, wheres)
739778
else
740779
for alias in aliases
741780
print(io, first ? "Union{" : ", ")
742781
first = false
743782
env = alias[2]
744-
show_typealias(io, alias[1], x, alias[2])
783+
wheres = make_wheres(io, alias[2], x)
784+
show_typealias(io, alias[1], x, alias[2], wheres)
785+
show_wheres(io, wheres)
745786
end
746787
print(io, "}")
747788
end

test/show.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,15 +2070,21 @@ end
20702070
end
20712071

20722072
module M37012
2073+
export AValue, B2
20732074
struct AnInteger{S<:Integer} end
20742075
struct AStruct{N} end
20752076
const AValue{S} = Union{AStruct{S}, AnInteger{S}}
2077+
struct BStruct{T,S} end
2078+
const B2{S,T} = BStruct{T,S}
20762079
end
20772080
@test Base.make_typealias(M37012.AStruct{1}) === nothing
20782081
@test isempty(Base.make_typealiases(M37012.AStruct{1})[1])
20792082
@test string(M37012.AStruct{1}) == "$(curmod_prefix)M37012.AStruct{1}"
20802083
@test string(Union{Nothing, Number, Vector}) == "Union{Nothing, Number, Vector{T} where T}"
20812084
@test string(Union{Nothing, AbstractVecOrMat}) == "Union{Nothing, AbstractVecOrMat{T} where T}"
2085+
@test string(M37012.BStruct{T, T} where T) == "$(curmod_prefix)M37012.B2{T, T} where T"
2086+
@test string(M37012.BStruct{T, S} where {T<:Unsigned, S<:Signed}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Unsigned, S<:Signed}"
2087+
@test string(M37012.BStruct{T, S} where {T<:Signed, S<:T}) == "$(curmod_prefix)M37012.B2{S, T} where {T<:Signed, S<:T}"
20822088

20832089
@test sprint(show, :(./)) == ":((./))"
20842090
@test sprint(show, :((.|).(.&, b))) == ":((.|).((.&), b))"

0 commit comments

Comments
 (0)