Skip to content

Commit

Permalink
remove fallback hash method. fixes #12198
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Oct 27, 2017
1 parent c2bdb1f commit 4aa0205
Show file tree
Hide file tree
Showing 12 changed files with 37 additions and 26 deletions.
2 changes: 2 additions & 0 deletions base/Enums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Base.convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = convert(T,
Base.write(io::IO, x::Enum{T}) where {T<:Integer} = write(io, T(x))
Base.read(io::IO, ::Type{T}) where {T<:Enum} = T(read(io, Enums.basetype(T)))

Base.hash(x::Enum, h::UInt) = Base.hash_uint(3h - object_id(x))

# generate code to test whether expr is in the given set of values
function membershiptest(expr, values)
lo, hi = extrema(values)
Expand Down
2 changes: 1 addition & 1 deletion base/atomics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ function atomic_min! end
unsafe_convert(::Type{Ptr{T}}, x::Atomic{T}) where {T} = convert(Ptr{T}, pointer_from_objref(x))
setindex!(x::Atomic{T}, v) where {T} = setindex!(x, convert(T, v))

const llvmtypes = Dict(
const llvmtypes = ObjectIdDict(
Bool => "i1",
Int8 => "i8", UInt8 => "i8",
Int16 => "i16", UInt16 => "i16",
Expand Down
4 changes: 2 additions & 2 deletions base/dates/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ const CONVERSION_SPECIFIERS = Dict{Char, Type}(
# Default values are needed when a conversion specifier is used in a DateFormat for parsing
# and we have reached the end of the input string.
# Note: Allow `Any` value as a default to support extensibility
const CONVERSION_DEFAULTS = Dict{Type, Any}(
const CONVERSION_DEFAULTS = ObjectIdDict(
Year => Int64(1),
Month => Int64(1),
DayOfWeekToken => Int64(0),
Expand All @@ -282,7 +282,7 @@ const CONVERSION_DEFAULTS = Dict{Type, Any}(

# Specifies the required fields in order to parse a TimeType
# Note: Allows for addition of new TimeTypes
const CONVERSION_TRANSLATIONS = Dict{Type{<:TimeType}, Tuple}(
const CONVERSION_TRANSLATIONS = ObjectIdDict(
Date => (Year, Month, Day),
DateTime => (Year, Month, Day, Hour, Minute, Second, Millisecond),
Time => (Hour, Minute, Second, Millisecond, Microsecond, Nanosecond),
Expand Down
2 changes: 1 addition & 1 deletion base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ for (Bsig, A1sig, A2sig, gbb, funcname) in
(SparseMatrixCSC , BitArray , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , SparseMatrixCSC , BitArray, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
)
@eval let cache = Dict{Function,Function}()
@eval let cache = ObjectIdDict()
global $funcname
function $funcname(f::Function, B::$Bsig, A1::$A1sig, A2::$A2sig)
func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC)
Expand Down
12 changes: 10 additions & 2 deletions base/distributed/clusterserialize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ function serialize(s::ClusterSerializer, g::GlobalRef)
invoke(serialize, Tuple{AbstractSerializer, GlobalRef}, s, g)
end

function hash_any(@nospecialize x)
try
return hash(x)
catch
return object_id(x)
end
end

# Send/resend a global object if
# a) has not been sent previously, i.e., we are seeing this object_id for the first time, or,
# b) hash value has changed or
Expand All @@ -114,7 +122,7 @@ function syms_2b_sent(s::ClusterSerializer, identifier)
oid = object_id(v)
if haskey(s.glbs_sent, oid)
# We have sent this object before, see if it has changed.
s.glbs_sent[oid] != hash(sym, hash(v)) && push!(lst, sym)
s.glbs_sent[oid] != hash(sym, hash_any(v)) && push!(lst, sym)
else
push!(lst, sym)
end
Expand Down Expand Up @@ -143,7 +151,7 @@ function serialize_global_from_main(s::ClusterSerializer, sym)
end
end
end
record_v && (s.glbs_sent[oid] = hash(sym, hash(v)))
record_v && (s.glbs_sent[oid] = hash(sym, hash_any(v)))

serialize(s, isconst(Main, sym))
serialize(s, v)
Expand Down
6 changes: 3 additions & 3 deletions base/distributed/workerpool.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ mutable struct CachingPool <: AbstractWorkerPool
channel::Channel{Int}
workers::Set{Int}

# Mapping between a tuple (worker_id, f) and a remote_ref
map_obj2ref::Dict{Tuple{Int, Function}, RemoteChannel}
# Mapping from a tuple (worker_id, f) to a remote_ref
map_obj2ref::ObjectIdDict

function CachingPool()
wp = new(Channel{Int}(typemax(Int)), Set{Int}(), Dict{Int, Function}())
wp = new(Channel{Int}(typemax(Int)), Set{Int}(), ObjectIdDict())
finalizer(wp, clear!)
wp
end
Expand Down
12 changes: 6 additions & 6 deletions base/hashing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ Typically, any type that implements `hash` should also implement its own `==` (h
hash(x::Any) = hash(x, zero(UInt))
hash(w::WeakRef, h::UInt) = hash(w.value, h)

## hashing general objects ##

hash(@nospecialize(x), h::UInt) = hash_uint(3h - object_id(x))
# some types for which == and === are the same
hash(x::Union{Symbol,Slot,TypeName,Method,Module,Void,Core.IntrinsicFunction}, h::UInt) = hash_uint(3h - object_id(x))

## core data hashing functions ##

Expand Down Expand Up @@ -67,12 +66,13 @@ end
## symbol & expression hashing ##

if UInt === UInt64
hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x83c7900696d26dc6))
hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x83c7900696d26dc6))
hash(x::QuoteNode, h::UInt) = hash(x.value, h + 0x2c97bf8b3de87020)
else
hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x96d26dc6))
hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x96d26dc6))
hash(x::QuoteNode, h::UInt) = hash(x.value, h + 0x469d72af)
end

hash(x::QuoteNode, h::UInt) = hash(x.value, hash(QuoteNode, h))

# hashing ranges by component at worst leads to collisions for very similar ranges
const hashr_seed = UInt === UInt64 ? 0x80707b6821b70087 : 0x21b70087
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/parse/config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ end

Config() = Config(Function[], Function[], InnerConfig())

const META = Dict{Function, Dict{Symbol, Any}}()
const META = ObjectIdDict()

getset(coll, key, default) = coll[key] = get(coll, key, default)

Expand Down
12 changes: 6 additions & 6 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ function instances end

# subtypes
function _subtypes(m::Module, x::Union{DataType,UnionAll},
sts=Set{Union{DataType,UnionAll}}(), visited=Set{Module}())
sts=ObjectIdDict(), visited=Set{Module}())
push!(visited, m)
xt = unwrap_unionall(x)
if !isa(xt, DataType)
Expand All @@ -521,7 +521,7 @@ function _subtypes(m::Module, x::Union{DataType,UnionAll},
t = t::DataType
if t.name.name === s && supertype(t).name == xt.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
ti != Bottom && push!(sts, ti=>true)
end
elseif isa(t, UnionAll)
t = t::UnionAll
Expand All @@ -530,7 +530,7 @@ function _subtypes(m::Module, x::Union{DataType,UnionAll},
tt = tt::DataType
if tt.name.name === s && supertype(tt).name == xt.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
ti != Bottom && push!(sts, ti=>true)
end
elseif isa(t, Module)
t = t::Module
Expand All @@ -544,14 +544,14 @@ end
function _subtypes_in(mods::Array, x::Union{DataType,UnionAll})
if !isabstract(x)
# Fast path
return Union{DataType,UnionAll}[]
return Any[]
end
sts = Set{Union{DataType,UnionAll}}()
sts = ObjectIdDict()
visited = Set{Module}()
for m in mods
_subtypes(m, x, sts, visited)
end
return sort!(collect(sts), by=string)
return sort!(collect(Any, keys(sts)), by=string)
end

subtypes(m::Module, x::Union{DataType,UnionAll}) = _subtypes_in([m], x)
Expand Down
4 changes: 2 additions & 2 deletions base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ mutable struct MIState
interface::ModalInterface
current_mode::TextInterface
aborted::Bool
mode_state::Dict
mode_state::ObjectIdDict
kill_ring::Vector{String}
kill_idx::Int
previous_key::Vector{Char}
Expand Down Expand Up @@ -1949,7 +1949,7 @@ init_state(terminal, prompt::Prompt) =
#=indent(spaces)=# -1, Threads.SpinLock(), 0.0)

function init_state(terminal, m::ModalInterface)
s = MIState(m, m.modes[1], false, Dict{Any,Any}())
s = MIState(m, m.modes[1], false, ObjectIdDict())
for mode in m.modes
s.mode_state[mode] = init_state(terminal, mode)
end
Expand Down
4 changes: 2 additions & 2 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operato
!first && print(io, sep)
parens = !is_quoted(item) &&
(first && prec >= prec_power &&
((item isa Expr && item.head === :call && item.args[1] in uni_ops) ||
((item isa Expr && item.head === :call && item.args[1] isa Symbol && item.args[1] in uni_ops) ||
(item isa Real && item < 0))) ||
(enclose_operators && item isa Symbol && isoperator(item))
parens && print(io, '(')
Expand Down Expand Up @@ -922,7 +922,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
func = args[1]
fname = isa(func,GlobalRef) ? func.name : func
func_prec = operator_precedence(fname)
if func_prec > 0 || fname in uni_ops
if func_prec > 0 || (fname isa Symbol && fname in uni_ops)
func = fname
end
func_args = args[2:end]
Expand Down
1 change: 1 addition & 0 deletions test/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ end

mutable struct Alpha end
Base.show(io::IO, ::Alpha) = print(io,"α")
Base.hash(a::Alpha, h::UInt) = xor(h, object_id(a))
@testset "issue #9463" begin
sbuff = IOBuffer()
io = Base.IOContext(sbuff, :limit => true, :displaysize => (10, 20))
Expand Down

0 comments on commit 4aa0205

Please sign in to comment.