Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: remove fallback hash method. fixes #12198 #24354

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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