diff --git a/base/hashing.jl b/base/hashing.jl index c409d3ae7940f..01274e3182245 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -34,8 +34,8 @@ hash(data::Any) = hash(data, HASH_SEED) hash(w::WeakRef, h::UInt) = hash(w.value, h) # Types can't be deleted, so marking as total allows the compiler to look up the hash -hash(T::Type, h::UInt) = - hash((@assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T)), h) +@noinline _jl_type_hash(T::Type) = @assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T) +hash(T::Type, h::UInt) = hash(_jl_type_hash(T), h) hash(@nospecialize(data), h::UInt) = hash(objectid(data), h) function mul_parts(a::UInt64, b::UInt64) diff --git a/test/hashing.jl b/test/hashing.jl index 41a1d525961cc..4e05b8a0102eb 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -308,4 +308,10 @@ struct AUnionParam{T<:Union{Nothing,Float32,Float64}} end @test hash(5//3) == hash(big(5)//3) end -@test Core.Compiler.is_foldable_nothrow(Base.infer_effects(hash, Tuple{Type{Int}, UInt})) +@testset "concrete eval type hash" begin + @test Core.Compiler.is_foldable_nothrow(Base.infer_effects(hash, Tuple{Type{Int}, UInt})) + + f(h...) = hash(Char, h...); + src = only(code_typed(f, Tuple{UInt}))[1] + @test count(stmt -> Meta.isexpr(stmt, :foreigncall), src.code) == 0 +end