Skip to content

Commit

Permalink
abstractdict: Create separate error type wrong-key insertions (JuliaL…
Browse files Browse the repository at this point in the history
…ang#41778)

Previously we were trying to do string formatting in Core.Compiler,
where this functionality is unavailable. Create a separate type
that can be thrown regardless of whether string processing is
available.
  • Loading branch information
Keno authored Nov 3, 2023
1 parent e98aaba commit 746cfdf
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 9 deletions.
2 changes: 2 additions & 0 deletions base/abstractdict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ struct KeyError <: Exception
key
end

KeyTypeError(K, key) = TypeError(:var"dict key", K, key)

const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__

haskey(d::AbstractDict, k) = in(k, keys(d))
Expand Down
6 changes: 3 additions & 3 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ function setindex!(h::Dict{K,V}, v0, key0) where V where K
else
key = convert(K, key0)::K
if !(isequal(key, key0)::Bool)
throw(ArgumentError("$(limitrepr(key0)) is not a valid key for type $K"))
throw(KeyTypeError(K, key0))
end
end
setindex!(h, v0, key)
Expand Down Expand Up @@ -478,7 +478,7 @@ function get!(default::Callable, h::Dict{K,V}, key0) where V where K
else
key = convert(K, key0)::K
if !isequal(key, key0)
throw(ArgumentError("$(limitrepr(key0)) is not a valid key for type $K"))
throw(KeyTypeError(K, key0))
end
end
return get!(default, h, key)
Expand Down Expand Up @@ -786,7 +786,7 @@ function mergewith!(combine, d1::Dict{K, V}, d2::AbstractDict) where {K, V}
if !(k isa K)
k1 = convert(K, k)::K
if !isequal(k, k1)
throw(ArgumentError("$(limitrepr(k)) is not a valid key for type $K"))
throw(KeyTypeError(K, k))
end
k = k1
end
Expand Down
6 changes: 4 additions & 2 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ function showerror(io::IO, ex::TypeError)
print(io, "TypeError: ")
if ex.expected === Bool
print(io, "non-boolean (", typeof(ex.got), ") used in boolean context")
elseif ex.func === :var"dict key"
print(io, "$(limitrepr(ex.got)) is not a valid key for type $(ex.expected)")
else
if isvarargtype(ex.got)
targs = (ex.got,)
Expand All @@ -80,7 +82,7 @@ function showerror(io::IO, ex::TypeError)
end
if ex.context == ""
ctx = "in $(ex.func)"
elseif ex.func === Symbol("keyword argument")
elseif ex.func === :var"keyword argument"
ctx = "in keyword argument $(ex.context)"
else
ctx = "in $(ex.func), in $(ex.context)"
Expand Down Expand Up @@ -787,7 +789,7 @@ function show_backtrace(io::IO, t::Vector)

if length(filtered) == 1 && StackTraces.is_top_level_frame(filtered[1][1])
f = filtered[1][1]::StackFrame
if f.line == 0 && f.file === Symbol("")
if f.line == 0 && f.file === :var""
# don't show a single top-level frame with no location info
return
end
Expand Down
2 changes: 1 addition & 1 deletion base/iddict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function sizehint!(d::IdDict, newsz)
end

function setindex!(d::IdDict{K,V}, @nospecialize(val), @nospecialize(key)) where {K, V}
!isa(key, K) && throw(ArgumentError("$(limitrepr(key)) is not a valid key for type $K"))
!isa(key, K) && throw(KeyTypeError(K, key))
if !(val isa V) # avoid a dynamic call
val = convert(V, val)::V
end
Expand Down
6 changes: 3 additions & 3 deletions test/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -639,13 +639,13 @@ end
@test d == IdDict(1=>1, 2=>2, 3=>3)
@test eltype(d) == Pair{Int,Int}
@test_throws KeyError d[:a]
@test_throws ArgumentError d[:a] = 1
@test_throws TypeError d[:a] = 1
@test_throws MethodError d[1] = :a

# copy constructor
d = IdDict(Pair(1,1), Pair(2,2), Pair(3,3))
@test collect(values(IdDict{Int,Float64}(d))) == collect(values(d))
@test_throws ArgumentError IdDict{Float64,Int}(d)
@test_throws TypeError IdDict{Float64,Int}(d)

# misc constructors
@test typeof(IdDict(1=>1, :a=>2)) == IdDict{Any,Int}
Expand All @@ -672,7 +672,7 @@ end
@test_throws MethodError get!(d, "b", "b")
@test delete!(d, "a") === d
@test !haskey(d, "a")
@test_throws ArgumentError get!(IdDict{Symbol,Any}(), 2, "b")
@test_throws TypeError get!(IdDict{Symbol,Any}(), 2, "b")
@test get!(IdDict{Int,Int}(), 1, 2.0) === 2
@test get!(()->2.0, IdDict{Int,Int}(), 1) === 2

Expand Down

0 comments on commit 746cfdf

Please sign in to comment.