Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix printing of TypeVar with lower bound. #16221

Merged
merged 1 commit into from
May 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -148,21 +148,29 @@ end

show(io::IO, x::TypeConstructor) = show(io, x.body)

function show_type_parameter(io::IO, p::ANY)
if p === String
print(io, "String")
else
function show_type_parameter(io::IO, p::ANY, has_tvar_env::Bool)
if has_tvar_env
show(io, p)
else
show(IOContext(io, :tvar_env, true), p)
end
end

function show(io::IO, x::DataType)
show(io, x.name)
if (!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple
# tvar_env is a `::Vector{Any}` when we are printing a method signature
# and `true` if we are printing type parameters outside a method signature.
has_tvar_env = get(io, :tvar_env, false) !== false
if ((!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple &&
!(has_tvar_env && x.name.primary === x))
# Do not print the type parameters for the primary type if we are
# 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, '{')
n = length(x.parameters)
for (i, p) in enumerate(x.parameters)
show_type_parameter(io, p)
show_type_parameter(io, p, has_tvar_env)
i < n && print(io, ',')
end
print(io, '}')
Expand Down Expand Up @@ -922,13 +930,22 @@ function ismodulecall(ex::Expr)
end

function show(io::IO, tv::TypeVar)
# If `tvar_env` exist and we are in it, the type constraint are
# already printed and we don't need to print it again.
# Otherwise, the lower bound should be printed if it is not `Bottom`
# and the upper bound should be printed if it is not `Any`.
# The upper bound `Any` should also be printed if we are not in the
# existing `tvar_env` in order to resolve the ambiguity when printing a
# method signature.
# i.e. `foo{T,N}(::Array{T,N}, ::Vector)` should be printed as
# `foo{T,N}(::Array{T,N}, ::Array{T<:Any,1})`
tvar_env = isa(io, IOContext) && get(io, :tvar_env, false)
if isa(tvar_env, Vector{Any})
have_env = true
in_env = (tv in tvar_env::Vector{Any})
else
have_env = false
in_env = true
in_env = false
end
if !in_env && !is(tv.lb, Bottom)
show(io, tv.lb)
Expand Down
4 changes: 4 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,15 @@ let t13464 = "hey there sailor"
end
end

# PR 13825
let ex = :(a + b)
@test string(ex) == "a + b"
ex.typ = Integer
@test string(ex) == "(a + b)::Integer"
end
foo13825{T,N}(::Array{T,N}, ::Array, ::Vector) = nothing
@test startswith(string(first(methods(foo13825))),
"foo13825{T,N}(::Array{T,N}, ::Array, ::Array{T<:Any,1})")

type TLayout
x::Int8
Expand Down
4 changes: 2 additions & 2 deletions test/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ let err_str,
@test sprint(show, which(:a, Tuple{})) == "(::Symbol)() at $sp:$(method_defs_lineno + 1)"
@test sprint(show, which(EightBitType, Tuple{})) == "EightBitType() at $sp:$(method_defs_lineno + 2)"
@test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == "(::EightBitType)() at $sp:$(method_defs_lineno + 3)"
@test sprint(show, which(EightBitTypeT, Tuple{})) == "(::Type{EightBitTypeT{T<:Any}})() at $sp:$(method_defs_lineno + 4)"
@test sprint(show, which(EightBitTypeT, Tuple{})) == "(::Type{EightBitTypeT})() at $sp:$(method_defs_lineno + 4)"
@test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == "(::Type{EightBitTypeT{T}}){T}() at $sp:$(method_defs_lineno + 5)"
@test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::EightBitTypeT{T<:Any})() at $sp:$(method_defs_lineno + 6)"
@test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::EightBitTypeT)() at $sp:$(method_defs_lineno + 6)"
@test startswith(sprint(show, which(Base.(Symbol("@doc")), Tuple{Vararg{Any}})), "@doc(x...) at boot.jl:")
@test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::FunctionLike)() at $sp:$(method_defs_lineno + 7)")
@test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)"
Expand Down
8 changes: 8 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,11 @@ let x = [], y = []
push!(y, x)
@test replstr(x) == "1-element Array{Any,1}:\n Any[Any[Any[#= circular reference @-2 =#]]]"
end

# PR 16221
# Printing of upper and lower bound of a TypeVar
@test string(TypeVar(:V, Signed, Real, false)) == "Signed<:V<:Real"
# Printing of primary type in type parameter place should not show the type
# parameter names.
@test string(Array) == "Array{T,N}"
@test string(Tuple{Array}) == "Tuple{Array}"