-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
hash(::Type)
inconsistent with some signature tuples (sometimes)
#49620
Comments
On current master, it seems that the
|
We eventually need to swap objectid for the actual hash function that agrees with == It is implemented in jltypes.c, because the runtime needs it, but it never got exported to Julia so that Dict would work correctly (only IdDict) |
@vtjnash, I'm not sure what you mean;
There is a diff --git a/src/jltypes.c b/src/jltypes.c
index 902e1e557f..b337fba043 100644
--- a/src/jltypes.c
+++ b/src/jltypes.c
@@ -1575,6 +1575,12 @@ static unsigned type_hash(jl_value_t *kj, int *failed) JL_NOTSAFEPOINT
}
}
+JL_DLLEXPORT uintptr_t jl_type_hash(jl_value_t *v) JL_NOTSAFEPOINT
+{
+ int *failed = 0;
+ return type_hash(v, failed);
+}
+
static unsigned typekey_hash(jl_typename_t *tn, jl_value_t **key, size_t n, int nofail) JL_NOTSAFEPOINT
{
if (tn == jl_type_typename && key[0] == jl_bottom_type)
diff --git a/src/julia.h b/src/julia.h
index 0a542dd8b6..89fea54fc4 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -1403,6 +1403,7 @@ JL_DLLEXPORT int jl_egal__bits(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_v
JL_DLLEXPORT int jl_egal__special(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_value_t *b JL_MAYBE_UNROOTED, jl_datatype_t *dt) JL_NOTSAFEPOINT;
JL_DLLEXPORT int jl_egal__unboxed(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_value_t *b JL_MAYBE_UNROOTED, jl_datatype_t *dt) JL_NOTSAFEPOINT;
JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) JL_NOTSAFEPOINT;
+JL_DLLEXPORT uintptr_t jl_type_hash(jl_value_t *v) JL_NOTSAFEPOINT;
STATIC_INLINE int jl_egal__unboxed_(const jl_value_t *a JL_MAYBE_UNROOTED, const jl_value_t *b JL_MAYBE_UNROOTED, jl_datatype_t *dt) JL_NOTSAFEPOINT
{ gives us
|
That is not a problem for |
That implementation of |
The fact that they're |
Currently, `hash(::Type, ::UInt)` uses `objectid`, which can have some odd behavior for types: in particular, subsequent identical type-valued variable definitions can have `objectid`s which differ from the first such definition. This has some bizarre downstream effects when e.g. using types as the values of a `Set` or the keys of a `Dict`. See issue 49620 for examples. There is an internal `type_hash` C function used for caching types but isn't exposed to Julia, as Jameson pointed out in the linked issue. This commit exposes it as `jl_type_hash` which is then used via `ccall` to define a method `hash(::Type, ::UInt)`. This method then fixes #49620. Note, however, that this does not affect the differing `objectid`s for otherwise identical types.
Currently, `hash(::Type, ::UInt)` uses `objectid`, which can have some odd behavior for types: in particular, subsequent identical type-valued variable definitions can have `objectid`s which differ from the first such definition. This has some bizarre downstream effects when e.g. using types as the values of a `Set` or the keys of a `Dict`. See issue 49620 for examples. There is an internal `type_hash` C function used for caching types but isn't exposed to Julia, as Jameson pointed out in the linked issue. This commit exposes it as `jl_type_hash` which is then used via `ccall` to define a method `hash(::Type, ::UInt)`. This method then fixes #49620. Note, however, that this does not affect the differing `objectid`s for otherwise identical types.
Currently, `hash(::Type, ::UInt)` uses `objectid`, which can have some odd behavior for types: in particular, subsequent identical type-valued variable definitions can have `objectid`s which differ from the first such definition. This has some bizarre downstream effects when e.g. using types as the values of a `Set` or the keys of a `Dict`. See issue 49620 for examples. There is an internal `type_hash` C function used for caching types but isn't exposed to Julia, as Jameson pointed out in the linked issue. This commit exposes it as `jl_type_hash` which is then used via `ccall` to define a method `hash(::Type, ::UInt)`. This method then fixes #49620. Note, however, that this does not affect the differing `objectid`s for otherwise identical types.
Currently, `hash(::Type, ::UInt)` uses `objectid`, which can have some odd behavior for types: in particular, subsequent identical type-valued variable definitions can have `objectid`s which differ from the first such definition. This has some bizarre downstream effects when e.g. using types as the values of a `Set` or the keys of a `Dict`. See issue 49620 for examples. There is an internal `type_hash` C function used for caching types but isn't exposed to Julia, as Jameson pointed out in the linked issue. This commit exposes it as `jl_type_hash` which is then used via `ccall` to define a method `hash(::Type, ::UInt)`. This method then fixes #49620. Note, however, that this does not affect the differing `objectid`s for otherwise identical types.
Currently, `hash(::Type, ::UInt)` uses `objectid`, which can have some odd behavior for types: in particular, subsequent identical type-valued variable definitions can have `objectid`s which differ from the first such definition. This has some bizarre downstream effects when e.g. using types as the values of a `Set` or the keys of a `Dict`. See issue 49620 for examples. There is an internal `type_hash` C function used for caching types but isn't exposed to Julia, as Jameson pointed out in the linked issue. This commit exposes it as `jl_type_hash` which is then used via `ccall` to define a method `hash(::Type, ::UInt)`. This method then fixes #49620. Note, however, that this does not affect the differing `objectid`s for otherwise identical types. (cherry picked from commit 633d1ae)
Bit of an heisenbug, but in some cases, the
hash()
function for signature tuples yields inconsistent hashes. @ararslan was able to see this in a clean Julia session:I couldn't actually precisely replicate this, but the issue definitely exists, since it causes Documenter to relatively consistently fail when checking missing docstrings in JuliaStats/StatsBase.jl#863. However, even that is not 100% consistent -- it did seem to depend on whether I included Revise or not at some point.
In a nutshell, Documenter needs to do a
signature in existing_signatures
check (whereexisting_signatures :: Set{Type}
). But thein
doesn't work properly. The bad hashing leads to:I checked the StatsBase docs build failure on 1.8.5 and 1.9.0-rc3.
X-ref: https://julialang.slack.com/archives/C66L48G1X/p1683135789756359
The text was updated successfully, but these errors were encountered: