From 3ae577e38a19150d2358e63eeb412b3beff70ec7 Mon Sep 17 00:00:00 2001 From: TEC Date: Mon, 29 Jul 2024 01:52:11 +0800 Subject: [PATCH] Add object field to KeyError Adding an optional field to KeyError that records the object the KeyError relates to allows for more sophisticated error messaging that can suggest potentially intended keys. --- base/abstractdict.jl | 5 ++++- base/bitset.jl | 2 +- base/compiler/cicache.jl | 2 +- base/dict.jl | 8 ++++---- base/env.jl | 2 +- base/iddict.jl | 4 ++-- base/idset.jl | 2 +- base/loading.jl | 2 +- base/set.jl | 2 +- base/show.jl | 2 +- base/stream.jl | 2 +- base/terminfo.jl | 2 +- base/weakkeydict.jl | 8 ++++---- 13 files changed, 23 insertions(+), 20 deletions(-) diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 62a5b3ee9e1b0..842ad2a161048 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -9,9 +9,12 @@ An indexing operation into an `AbstractDict` (`Dict`) or `Set` like object tried delete a non-existent element. """ struct KeyError <: Exception + object key end +KeyError(key) = KeyError(nothing, key) + KeyTypeError(K, key) = TypeError(:var"dict key", K, key) const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ @@ -541,7 +544,7 @@ end function getindex(t::AbstractDict{<:Any,V}, key) where V v = get(t, key, secret_table_token) if v === secret_table_token - throw(KeyError(key)) + throw(KeyError(t, key)) end return v::V end diff --git a/base/bitset.jl b/base/bitset.jl index 78d8fc8769de1..2fc9e330004a9 100644 --- a/base/bitset.jl +++ b/base/bitset.jl @@ -263,7 +263,7 @@ push!(s::BitSet, ns::Integer...) = (for n in ns; push!(s, n); end; s) delete!(s, n) n else - throw(KeyError(n)) + throw(KeyError(s, n)) end end diff --git a/base/compiler/cicache.jl b/base/compiler/cicache.jl index a6ed18fe5105f..911ce4e051e47 100644 --- a/base/compiler/cicache.jl +++ b/base/compiler/cicache.jl @@ -63,7 +63,7 @@ end function getindex(wvc::WorldView{InternalCodeCache}, mi::MethodInstance) r = get(wvc, mi, nothing) - r === nothing && throw(KeyError(mi)) + r === nothing && throw(KeyError(wvc, mi)) return r::CodeInstance end diff --git a/base/dict.jl b/base/dict.jl index 4a63ed364b64d..da5ffdd6c1d0a 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -474,7 +474,7 @@ end function getindex(h::Dict{K,V}, key) where V where K index = ht_keyindex(h, key) - return index < 0 ? throw(KeyError(key)) : @assume_effects :noub @inbounds h.vals[index]::V + return index < 0 ? throw(KeyError(h, key)) : @assume_effects :noub @inbounds h.vals[index]::V end """ @@ -580,7 +580,7 @@ end function pop!(h::Dict, key) index = ht_keyindex(h, key) - return index > 0 ? _pop!(h, index) : throw(KeyError(key)) + return index > 0 ? _pop!(h, index) : throw(KeyError(h, key)) end """ @@ -822,7 +822,7 @@ function getindex(dict::ImmutableDict, key) isequal(dict.key, key) && return dict.value dict = dict.parent end - throw(KeyError(key)) + throw(KeyError(dict, key)) end function get(dict::ImmutableDict, key, default) while isdefined(dict, :parent) @@ -982,7 +982,7 @@ end function getindex(dict::PersistentDict{K,V}, key::K) where {K,V} found = KeyValue.get(dict, key) - found === nothing && throw(KeyError(key)) + found === nothing && throw(KeyError(dict, key)) return only(found) end diff --git a/base/env.jl b/base/env.jl index 6248f1933d1ec..f8a53ad345758 100644 --- a/base/env.jl +++ b/base/env.jl @@ -161,7 +161,7 @@ function parse_bool_env(name::String, val::String = ENV[name]; throw::Bool=false end end -getindex(::EnvDict, k::AbstractString) = access_env(k->throw(KeyError(k)), k) +getindex(::EnvDict, k::AbstractString) = access_env(k->throw(KeyError(ENV, k)), k) get(::EnvDict, k::AbstractString, def) = access_env(Returns(def), k) get(f::Callable, ::EnvDict, k::AbstractString) = access_env(k->f(), k) function get!(default::Callable, ::EnvDict, k::AbstractString) diff --git a/base/iddict.jl b/base/iddict.jl index 9c133d5ba23c6..650a19dd0a357 100644 --- a/base/iddict.jl +++ b/base/iddict.jl @@ -95,7 +95,7 @@ end function getindex(d::IdDict{K,V}, @nospecialize(key)) where {K, V} val = ccall(:jl_eqtable_get, Any, (Any, Any, Any), d.ht, key, secret_table_token) - val === secret_table_token && throw(KeyError(key)) + val === secret_table_token && throw(KeyError(d, key)) return val::V end @@ -113,7 +113,7 @@ end function pop!(d::IdDict{K,V}, @nospecialize(key)) where {K, V} val = pop!(d, key, secret_table_token) - val === secret_table_token && throw(KeyError(key)) + val === secret_table_token && throw(KeyError(d, key)) return val::V end diff --git a/base/idset.jl b/base/idset.jl index c46d49968ff73..82f2f07b54c3e 100644 --- a/base/idset.jl +++ b/base/idset.jl @@ -74,7 +74,7 @@ function _pop!(s::IdSet, @nospecialize(x)) end removed end -pop!(s::IdSet, @nospecialize(x)) = _pop!(s, x) == -1 ? throw(KeyError(x)) : x +pop!(s::IdSet, @nospecialize(x)) = _pop!(s, x) == -1 ? throw(KeyError(s, x)) : x pop!(s::IdSet, @nospecialize(x), @nospecialize(default)) = _pop!(s, x) == -1 ? default : x delete!(s::IdSet, @nospecialize(x)) = (_pop!(s, x); s) diff --git a/base/loading.jl b/base/loading.jl index 4dc735f0099d8..f08fef63150da 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2366,7 +2366,7 @@ end root_module(key::PkgId) = @lock require_lock loaded_modules[key] function root_module(where::Module, name::Symbol) key = identify_package(where, String(name)) - key isa PkgId || throw(KeyError(name)) + key isa PkgId || throw(KeyError(where, name)) return root_module(key) end maybe_root_module(key::PkgId) = @lock require_lock get(loaded_modules, key, nothing) diff --git a/base/set.jl b/base/set.jl index 2f96cef626b6f..9982783b20a8f 100644 --- a/base/set.jl +++ b/base/set.jl @@ -150,7 +150,7 @@ end function pop!(s::Set, x) index = ht_keyindex(s.dict, x) - index < 1 && throw(KeyError(x)) + index < 1 && throw(KeyError(s, x)) result = @inbounds s.dict.keys[index] _delete!(s.dict, index) result diff --git a/base/show.jl b/base/show.jl index fa66a198aef4d..788cfafd219cc 100644 --- a/base/show.jl +++ b/base/show.jl @@ -421,7 +421,7 @@ in(key_value::Pair, io::IO) = false haskey(io::IOContext, key) = haskey(io.dict, key) haskey(io::IO, key) = false getindex(io::IOContext, key) = getindex(io.dict, key) -getindex(io::IO, key) = throw(KeyError(key)) +getindex(io::IO, key) = throw(KeyError(io, key)) get(io::IOContext, key, default) = get(io.dict, key, default) get(io::IO, key, default) = default keys(io::IOContext) = keys(io.dict) diff --git a/base/stream.jl b/base/stream.jl index a45307b883da8..e60748e13f261 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1287,7 +1287,7 @@ end # Deprecate these in v2 (RedirectStdStream support) iterate(p::Pipe) = (p.out, 1) iterate(p::Pipe, i::Int) = i == 1 ? (p.in, 2) : nothing -getindex(p::Pipe, key::Int) = key == 1 ? p.out : key == 2 ? p.in : throw(KeyError(key)) +getindex(p::Pipe, key::Int) = key == 1 ? p.out : key == 2 ? p.in : throw(KeyError(p, key)) """ redirect_stdout([stream]) -> stream diff --git a/base/terminfo.jl b/base/terminfo.jl index 79713f4a86aa3..c2cf3c0482f3f 100644 --- a/base/terminfo.jl +++ b/base/terminfo.jl @@ -226,7 +226,7 @@ function getindex(ti::TermInfo, key::Symbol) haskey(ti.numbers, key) && return ti.numbers[key] haskey(ti.strings, key) && return ti.strings[key] haskey(ti.aliases, key) && return getindex(ti, ti.aliases[key]) - throw(KeyError(key)) + throw(KeyError(ti, key)) end keys(ti::TermInfo) = keys(ti.flags) ∪ keys(ti.numbers) ∪ keys(ti.strings) ∪ keys(ti.aliases) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 1a98bf1ee4333..b2076ac930eb5 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -132,19 +132,19 @@ end map!(f, iter::ValueIterator{<:WeakKeyDict})= map!(f, values(iter.dict.ht)) function get(wkh::WeakKeyDict{K}, key, default) where {K} - key === nothing && throw(KeyError(nothing)) + key === nothing && throw(KeyError(wkh, nothing)) lock(wkh) do return get(wkh.ht, key, default) end end function get(default::Callable, wkh::WeakKeyDict{K}, key) where {K} - key === nothing && throw(KeyError(nothing)) + key === nothing && throw(KeyError(wkh, nothing)) lock(wkh) do return get(default, wkh.ht, key) end end function pop!(wkh::WeakKeyDict{K}, key) where {K} - key === nothing && throw(KeyError(nothing)) + key === nothing && throw(KeyError(wkh, nothing)) lock(wkh) do return pop!(wkh.ht, key) end @@ -175,7 +175,7 @@ function haskey(wkh::WeakKeyDict{K}, key) where {K} end end function getindex(wkh::WeakKeyDict{K}, key) where {K} - key === nothing && throw(KeyError(nothing)) + key === nothing && throw(KeyError(wkh, nothing)) lock(wkh) do return getindex(wkh.ht, key) end