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 🙂