Benjamin Dobell
03/30/2020, 7:32 AMMutableHashMap
, using the keys retrieved from the map itself. Does anyone know how that could be possible?
Attached is a screenshot of the seemingly contradictory debugger outputs.
I should note, this isn’t just an issue with the debugger. In practice I’m inserting a key into a map, then almost immediately retrieving (further up the same call stack) using the exact same key and getting back null
for the value corresponding to that key. There’s no multi-threaded access to this map etc.
hashCode
and equals
are stable for said key.
This is using Jetbrain’s runtime.Michael de Kaste
03/30/2020, 7:47 AMBenjamin Dobell
03/30/2020, 8:01 AMITy
) with strings. As the ITy
effectively had a unique toString()
method. It’s just slower than it needs to be.
The insertion was essentially just:
tyProblems[someITy] = mutableListOf<Problem>()
and retrieval
tyProblems[someITy]
Where someITy
are not simply equivalent (equal) values, but rather the exact same value (reference).
I must admit, just based on the screenshot above, ignoring any possible code. I’m unclear how retrieving a value from a map using its own key could ever fail (assuming hashCode
and equals
are stable).
To add insult to injury, cloning the map (last inspection) then retrieving with that exact same key works just fine, 100% of the time 😐Benjamin Dobell
03/30/2020, 8:03 AMgetNode
i.e. the LinkedHashMap
implementation, however it would seem the source-code Jetbrains are distributing doesn’t match the binaries they’re distributing 😐Michael de Kaste
03/30/2020, 8:31 AMMichael de Kaste
03/30/2020, 8:32 AMBenjamin Dobell
03/30/2020, 8:33 AMMichael de Kaste
03/30/2020, 9:49 AM[]
you just use .get()
?David Eriksson
03/30/2020, 7:55 PMBenjamin Dobell
03/31/2020, 7:16 AMITy
keys again:
https://github.com/Benjamin-Dobell/IntelliJ-EmmyLua/commit/67f6ac58e57ac335c0c55ef00d66f4f6c184dc7e
Realistically, I don’t expect anyone to go pouring through my code. I know non-stable hashCode
and/or equals
could lead to something like the above; basically was hoping someone may generally know of something else that could lead to a similar outcome.
I was thinking perhaps something to do with Kotlin type safety/casting rejecting my ArrayList
value, however that theory was somewhat shot down by my last inspection where I clone the collection using the exact same type definition 🤷♂️Benjamin Dobell
03/31/2020, 7:18 AMLinkedHashMap
internals, and it’s seemingly getting a null
back from getNode
i.e. before Kotlin is even involved.Benjamin Dobell
03/31/2020, 7:23 AMITy
definition isn’t all that useful. The offending concrete type is TyUnion
(https://github.com/Benjamin-Dobell/IntelliJ-EmmyLua/blob/type-safety/src/main/java/com/tang/intellij/lua/ty/TyUnion.kt#L102-L110). Also, no I didn’t implement that equals
method. It’s stable, it’s just subject to “aliasing” (false positives) - I wouldn’t have written it like that 😉David Eriksson
03/31/2020, 7:23 AMhashCode
and equals
to your abstract Ty
class, that throws a NotImplementedError or similar?Benjamin Dobell
03/31/2020, 7:38 AMAn interface may not implement a method of 'Any'
compilation error if you try implement hashCode
or equals
in an interface.
There is however a concrete superclass called Ty
that in practice all classes that implement ITy
extend, so I added the implementations there.
Several types do indeed lead to an exception being raised. They’re (correctly) reliant on the default hashCode
and equals
implementations. I replaced it with a call to super’s implementation so I could more easily debug. The offending code does not call into this method, as expected `TyUnion`’s implementations are being hit instead, both when putting and attempting to get from the linked hash map.David Eriksson
03/31/2020, 7:45 AMBenjamin Dobell
03/31/2020, 9:20 AMhashCode
is demonstrably stable (inspections show this also). The hashCode
returned when setting and getting is identical (verified not just based on the inspections, but when debugging), yet no result is returned from the hash map. Honestly, it looks like a runtime bug to me. However, I can’t confirm that as I’ve no idea what code my computer is running seems as Jetbrains aren’t distributing the correct source for their forked OpenJDK JRE 😐Benjamin Dobell
03/31/2020, 10:17 AMhashCode
of one of these more complex types. It certainly seems a lot more feasible than a runtime bug in a class that is no doubt used a lot.
By that I mean, I think it’s conceivable an object is inserted into the map whilst its hashCode
is one value, then its hashCode
is changing there-after. However, I think when debugging my inspections are triggering that change in hashCode
, so it seems stable to me. I did debug hashCode
used during the put
process i.e. inside `LinkedHashMap`’s internals, but I think I must have looked at it just after it’s own internal call to hashCode
.
Nothing verified, but that’s my running theory. As far as I’m concerned it’d make significantly more sense if these classes were immutable, but I didn’t write them, only this particular piece of code utilising them.Benjamin Dobell
03/31/2020, 10:29 AMhashCode
.
I’m going to see what I can do about making these types immutable. Not my project, so might have some resistance, will see.
Thanks for your help everyone 🙂