andyferris / Dictionaries.jl

An alternative interface for dictionaries in Julia, for improved productivity and performance
Other
282 stars 28 forks source link

unsetting key can lead to undefined reference #84

Closed piever closed 2 years ago

piever commented 2 years ago

I've run into the following bug when calling unset! on a Dictionary. Somehow the values of the dictionary get corrupted, but it only happens with some data types.

julia> d = Dictionary{Symbol, Any}([:a, :b, :c, :d], [1, [1], [1], nothing])
4-element Dictionary{Symbol, Any}
 :a │ 1
 :b │ [1]
 :c │ [1]
 :d │ nothing

julia> unset!(d, :a)
3-element Dictionary{Symbol, Any}
 :b │ [1]
 :c │ [1]
 :d │ nothing

julia> d.values
4-element Vector{Any}:
 #undef
    [1]
    [1]
    nothing

On Dictionaries 0.3.16 this caused collect(pairs(d)) to fail (with access to undefined reference), but now (v0.3.17) that seems to work. Opening this in case it is worrisome that d.values and values(d) do not have the same content.

andyferris commented 2 years ago

Please note that d.values is not equivalent to values(d) because upon deletion the arrays have holes in them, which are skipped on iteration. So length(values(d)) == 3 but length(d.values) == 4 in this case. In 0.3.16 there were definitely bugs, but the described behavior here is now as intended and seems correct to me.

Does that make sense?

piever commented 2 years ago

Ah I see, yes it definitely makes sense that the array stored in d.values is an implementation detail, and it does makes sense to leave holes in it (rather than moving everything around) where removing an entry.