-
-
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
Type hashing breaks equality #26105
Comments
This is going to be quite difficult to fix. It seems to require being able to completely normalize types to a canonical form in which equality is equivalent to structure. For types, one typically wants to use |
As a defensive strategy, we return the same hash for all complex types until a solution is found. I'm not sure how to define "complex", but an extensive definition could include all non-concrete types. |
I think normalization already exists?
|
...so the low-effort ugly proposal would be to use |
Right, we could actually do some kind of "approximate normalization" – i.e. apply simplifications that aren't really correct but are roughly correct and use the resulting normalized type as a proxy for hashing. All you need is for |
Do we have an example where Or are you concerned that this is too expensive? |
I'm fairly certain there are cases where that happens. @JeffBezanson will have specific examples. |
We try to ensure this for concrete types (the cases where it fails are considered bugs), but it's a pretty expensive operation (can be a linear scan testing type-equal against all other types). |
Ref. #25430. Here is a failing example: julia> t1 = Vector{Tuple{Any}}
Array{Tuple{Any},1}
julia> t2 = Vector{Tuple{>:Int}}
Array{Tuple{#s1} where #s1>:Int64,1}
julia> t1 == t2
true
julia> type_normalize{t1} === type_normalize{t2}
false Note also that the current normalization code by design only ensures that for every concrete type Furthermore, assuming we had only one cache and it worked perfectly, the normalization would produce the first type-equal (concrete) type that had been instantiated in the session, so the calculated hash for the same type could differ between sessions. I don't know how problematic that is, but I think we usually try to avoid it. |
Right, what we're doing now is not intended to be normalization, just caching. I very much doubt it's worth using type equality ( |
What's wrong with the approximate normalization approach? Sure, using type equality in lookup may not be the most typical thing to do, but why not just make it correct? |
It seems to me that approximate normalization would still be quite expensive and also unclear how to implement. Taking the example in the OP, |
|
...this also affects dispatch. Separate bug, known bug or not-a-bug?
|
@JeffBezanson How about returning the same hash for all problematic types? |
It's not so easy to discern a problematic type. Is |
I wouldn't, but maybe Jeff would have... ;-) |
Nope, I wouldn't have :) |
So even if we could do More seriously, I think given a type, deciding a) "this as as simple as it gets" versus b) "there might be a simpler type equal to this one" might be doable (for some appropriate measure of "simple"). But either deciding for a type of class a) whether there is a more complicated type equal to it (but not already being normalized to it) or finding the simpler-but-equal type (if any) for a type of class b) seems much harder. So I guess what we really should be discussing is what the better alternative is: throwing an error when trying to hash a type or making all types hash equal? |
Hashing all types the same is the simplest function that's guaranteed to give the same hash value whenever the inputs are type-equal. The question is if we can compute a somewhat less simple function that still has this property. It does seem to be quite tricky to do so. |
I definitely think it would be better to make |
So you would then rename the current |
The dispatch example from above works as expected on 1.0.0:
|
This is captured by #35130 |
Both on 0.62 and current master.
The text was updated successfully, but these errors were encountered: