Skip to content

Commit

Permalink
Revert changes to get! with callable and add test.
Browse files Browse the repository at this point in the history
Fixes bug if for example the call to `default` mutated the dict.
  • Loading branch information
Zentrik committed Nov 14, 2023
1 parent 7218ee9 commit b24dff1
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 7 deletions.
13 changes: 6 additions & 7 deletions base/iddict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,16 @@ function get(default::Callable, d::IdDict{K,V}, @nospecialize(key)) where {K, V}
end

function get!(default::Callable, d::IdDict{K,V}, @nospecialize(key)) where {K, V}
keyindex, inserted = ht_keyindex!(d, key)

if inserted
val = ccall(:jl_eqtable_get, Any, (Any, Any, Any), d.ht, key, secret_table_token)
if val === secret_table_token
val = default()
if !(val isa V) # avoid a dynamic call
if !isa(val, V)
val = convert(V, val)::V
end
_setindex!(d, val, key, keyindex, inserted)
return val::V
setindex!(d, val, key)
return val
else
return @inbounds d.ht[keyindex+1]::V
return val::V
end
end

Expand Down
10 changes: 10 additions & 0 deletions test/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1610,3 +1610,13 @@ let d = Dict()
d[1.0] = 'b'
@test only(d) === Pair{Any,Any}(1.0, 'b')
end

# Check mutating IdDict during get! works
let d = IdDict()
function f()
d[1] = 4
return -2
end
@test get!(f, d, 1) === -2
@test length(d) == 1
end

0 comments on commit b24dff1

Please sign in to comment.