Repository: JuliaCollections/DataStructures.jl (julia)

Issue:
Base.in(x, KeySet{OrderedRobinDict}) should not use `get`
MWE:

```julia
## Incorrect answer if value is a negative Int
julia> d = OrderedRobinDict(:a => -3)
OrderedRobinDict{Symbol, Int64} with 1 entry:
  :a => -3

julia> :a in keys(d1)
false

# Completely errors out if value is not comparable against Int with >=

julia> d = OrderedRobinDict(1 => [1,2,3], 2 => [4,5,6])
OrderedRobinDict{Int64, Vector{Int64}} with 2 entries:
  1 => [1, 2, 3]
  2 => [4, 5, 6]

julia> 1 in keys(d)
ERROR: MethodError: no method matching isless(::Int64, ::Vector{Int64})

Closest candidates are:
  isless(::Real, ::ColorTypes.AbstractGray)
   @ ColorTypes C:\Users\mrufsvold\.julia\packages\ColorTypes\1dGw6\src\operations.jl:39
  isless(::AbstractVector, ::AbstractVector)
   @ Base abstractarray.jl:2911
  isless(::Real, ::AbstractFloat)
   @ Base operators.jl:178
  ...

Stacktrace:
 [1] <(x::Int64, y::Vector{Int64})
   @ Base .\operators.jl:343
 [2] <=(x::Int64, y::Vector{Int64})
   @ Base .\operators.jl:392
 [3] >=(x::Vector{Int64}, y::Int64)
   @ Base .\operators.jl:416
 [4] in(key::Int64, v::Base.KeySet{Int64, OrderedRobinDict{Int64, Vector{Int64}}})
   @ DataStructures C:\Users\mrufsvold\.julia\packages\DataStructures\59MD0\src\ordered_robin_dict.jl:306
 [5] top-level scope
   @ REPL[74]:1
```

Base.in is using `get` and checks if the value is greater than zero, causing all these problems.

Pull request description:
Resolves #857 

I am not sure if checking if the key appears in the key vector property is the right way to go. Open to another solution!

Patch:
diff --git a/src/ordered_robin_dict.jl b/src/ordered_robin_dict.jl
index 917e1a84b..141a5f757 100644
--- a/src/ordered_robin_dict.jl
+++ b/src/ordered_robin_dict.jl
@@ -132,7 +132,7 @@ function Base.setindex!(h::OrderedRobinDict{K, V}, v0, key0) where {K,V}
     else
         @assert haskey(h, key0)
         @inbounds orig_v = h.vals[index]
-        (orig_v != v0) && (@inbounds h.vals[index] = v0)
+        !isequal(orig_v, v0) && (@inbounds h.vals[index] = v0)
     end
 
     check_for_rehash(h) && rehash!(h)
@@ -305,8 +305,8 @@ julia> haskey(D, 'c')
 false
 ```
 """
-Base.haskey(h::OrderedRobinDict, key) = (get(h.dict, key, -2) > 0)
-Base.in(key, v::Base.KeySet{K,T}) where {K,T<:OrderedRobinDict{K}} = (get(v.dict, key, -1) >= 0)
+Base.haskey(h::OrderedRobinDict, key) = (get(h.dict, key, -1) > 0)
+Base.in(key, v::Base.KeySet{K,T}) where {K,T<:OrderedRobinDict{K}} = (get(v.dict.dict, key, -1) >= 0)
 
 """
     getkey(collection, key, default)


Test patch:
diff --git a/test/runtests.jl b/test/runtests.jl
index 33927d2a4..d44fe5bc5 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -8,7 +8,8 @@ import DataStructures: IntSet
 @test [] == detect_ambiguities(Core, DataStructures)
 @test [] == detect_ambiguities(Base, DataStructures)
 
-tests = ["deprecations",
+tests = [
+         "deprecations",
          "int_set",
          "sparse_int_set",
          "deque",
diff --git a/test/test_ordered_robin_dict.jl b/test/test_ordered_robin_dict.jl
index 2a78fc7aa..79efa6572 100644
--- a/test/test_ordered_robin_dict.jl
+++ b/test/test_ordered_robin_dict.jl
@@ -78,6 +78,13 @@
         @test od60[14] == 15
     end
 
+    @testset "Fixes issue 857" begin
+        h = OrderedRobinDict{Any,Any}([("a", missing), ("b", -2)])
+        @test 5 == (h["a"] = 5)
+        @test "b" in keys(h)
+        @test haskey(h,"b")
+    end
+
 
     # #############################
     # Copied and modified from Base/test/dict.jl