{"action":"created","issue":{"url":"https://api.github.com/repos/godotengine/godot/issues/24215","repository_url":"https://api.github.com/repos/godotengine/godot","labels_url":"https://api.github.com/repos/godotengine/godot/issues/24215/labels{/name}","comments_url":"https://api.github.com/repos/godotengine/godot/issues/24215/comments","events_url":"https://api.github.com/repos/godotengine/godot/issues/24215/events","html_url":"https://github.com/godotengine/godot/issues/24215","id":388770451,"node_id":"MDU6SXNzdWUzODg3NzA0NTE=","number":24215,"title":"Dictionary keys are stored by reference","user":{"login":"alkhimey","id":652603,"node_id":"MDQ6VXNlcjY1MjYwMw==","avatar_url":"https://avatars0.githubusercontent.com/u/652603?v=4","gravatar_id":"","url":"https://api.github.com/users/alkhimey","html_url":"https://github.com/alkhimey","followers_url":"https://api.github.com/users/alkhimey/followers","following_url":"https://api.github.com/users/alkhimey/following{/other_user}","gists_url":"https://api.github.com/users/alkhimey/gists{/gist_id}","starred_url":"https://api.github.com/users/alkhimey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alkhimey/subscriptions","organizations_url":"https://api.github.com/users/alkhimey/orgs","repos_url":"https://api.github.com/users/alkhimey/repos","events_url":"https://api.github.com/users/alkhimey/events{/privacy}","received_events_url":"https://api.github.com/users/alkhimey/received_events","type":"User","site_admin":false},"labels":[{"id":73330064,"node_id":"MDU6TGFiZWw3MzMzMDA2NA==","url":"https://api.github.com/repos/godotengine/godot/labels/bug","name":"bug","color":"ff2222","default":true},{"id":279097162,"node_id":"MDU6TGFiZWwyNzkwOTcxNjI=","url":"https://api.github.com/repos/godotengine/godot/labels/discussion","name":"discussion","color":"ee77ee","default":false},{"id":279097966,"node_id":"MDU6TGFiZWwyNzkwOTc5NjY=","url":"https://api.github.com/repos/godotengine/godot/labels/topic:core","name":"topic:core","color":"ffdd44","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/godotengine/godot/milestones/7","html_url":"https://github.com/godotengine/godot/milestone/7","labels_url":"https://api.github.com/repos/godotengine/godot/milestones/7/labels","id":2529217,"node_id":"MDk6TWlsZXN0b25lMjUyOTIxNw==","number":7,"title":"3.1","description":"","creator":{"login":"akien-mga","id":4701338,"node_id":"MDQ6VXNlcjQ3MDEzMzg=","avatar_url":"https://avatars0.githubusercontent.com/u/4701338?v=4","gravatar_id":"","url":"https://api.github.com/users/akien-mga","html_url":"https://github.com/akien-mga","followers_url":"https://api.github.com/users/akien-mga/followers","following_url":"https://api.github.com/users/akien-mga/following{/other_user}","gists_url":"https://api.github.com/users/akien-mga/gists{/gist_id}","starred_url":"https://api.github.com/users/akien-mga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akien-mga/subscriptions","organizations_url":"https://api.github.com/users/akien-mga/orgs","repos_url":"https://api.github.com/users/akien-mga/repos","events_url":"https://api.github.com/users/akien-mga/events{/privacy}","received_events_url":"https://api.github.com/users/akien-mga/received_events","type":"User","site_admin":false},"open_issues":919,"closed_issues":4792,"state":"open","created_at":"2017-05-18T13:33:56Z","updated_at":"2018-12-08T06:34:38Z","due_on":null,"closed_at":null},"comments":4,"created_at":"2018-12-07T18:45:13Z","updated_at":"2018-12-08T11:44:27Z","closed_at":null,"author_association":"NONE","body":"<!-- Please search existing issues for potential duplicates before filing yours:\r\nhttps://github.com/godotengine/godot/issues?q=is%3Aissue\r\n-->\r\n\r\n**Godot version:**\r\n3.0.6 stable\r\n\r\n\r\n**OS/device including version:**\r\nUbuntu Bionic 64bit\r\n\r\n\r\n**Issue description:**\r\n\r\n\tvar xx = {}\r\n\t\r\n\tvar k1 = [[1,2], [3,4]]\r\n\tvar k2 = [[1,2], [3,4]]\r\n\tvar v1 = [1,2,3]\r\n\txx[k1] = v1\r\n\tprint(xx.has(k2))\r\n\t\r\n\tk1[0][0] = 999\r\n\tprint(xx.has(k2))\r\n\t\r\n\tprint(xx.has(k1))\r\n\tprint(xx.keys())\r\n\r\nThe result:\r\n\r\n    True\r\n    False\r\n    False\r\n    [[[999, 2], [3, 4]]]\r\n\r\nThere are two issues here:\r\n\r\n1. Changing `k1` changes the key in the dictionary which implies that the key stored in the dictionary is actually a reference to `k1`. This might be the design and not a bug, but if it is the design, I am not sure how does it work with the hash of the key which is used to quickly find the value in the internal data structure. Additionally this is counter intuitive and not [documented](https://docs.godotengine.org/en/3.0/classes/class_dictionary.html).\r\n2. After changing `k1` there is no more way to retrieve the value. Both `k1` and `k2` considered not in the dictionary. This is most probably a bug."},"comment":{"url":"https://api.github.com/repos/godotengine/godot/issues/comments/445453171","html_url":"https://github.com/godotengine/godot/issues/24215#issuecomment-445453171","issue_url":"https://api.github.com/repos/godotengine/godot/issues/24215","id":445453171,"node_id":"MDEyOklzc3VlQ29tbWVudDQ0NTQ1MzE3MQ==","user":{"login":"alkhimey","id":652603,"node_id":"MDQ6VXNlcjY1MjYwMw==","avatar_url":"https://avatars0.githubusercontent.com/u/652603?v=4","gravatar_id":"","url":"https://api.github.com/users/alkhimey","html_url":"https://github.com/alkhimey","followers_url":"https://api.github.com/users/alkhimey/followers","following_url":"https://api.github.com/users/alkhimey/following{/other_user}","gists_url":"https://api.github.com/users/alkhimey/gists{/gist_id}","starred_url":"https://api.github.com/users/alkhimey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alkhimey/subscriptions","organizations_url":"https://api.github.com/users/alkhimey/orgs","repos_url":"https://api.github.com/users/alkhimey/repos","events_url":"https://api.github.com/users/alkhimey/events{/privacy}","received_events_url":"https://api.github.com/users/alkhimey/received_events","type":"User","site_admin":false},"created_at":"2018-12-08T11:44:27Z","updated_at":"2018-12-08T11:44:27Z","author_association":"NONE","body":"@pgruenbacher The relevant code I believe is [here](https://github.com/godotengine/godot/blob/35fbbeb99b3b2356ea86572f9c9f26c2523fcc8e/core/hash_map.h#L184)\r\n\r\n```\r\n/* I want to have only one function.. */\r\n\t_FORCE_INLINE_ const Element *get_element(const TKey &p_key) const {\r\n\r\n\t\tuint32_t hash = Hasher::hash(p_key);\r\n\t\tuint32_t index = hash & ((1 << hash_table_power) - 1);\r\n\r\n\t\tElement *e = hash_table[index];\r\n\r\n\t\twhile (e) {\r\n\r\n\t\t\t/* checking hash first avoids comparing key, which may take longer */\r\n\t\t\tif (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {\r\n\r\n\t\t\t\t/* the pair exists in this hashtable, so just update data */\r\n\t\t\t\treturn e;\r\n\t\t\t}\r\n\r\n\t\t\te = e->next;\r\n\t\t}\r\n\r\n\t\treturn NULL;\r\n}\r\n```\r\n\r\nMy conclusion is that after changing `r1`:\r\n`r1` does not have the correct hash anymore.\r\n`r2` has the correct hash but it's contents are different from `r1` ( [`Comparator::compare`](https://github.com/godotengine/godot/blob/5bd0ff003fdd82cf84a557251633ebb83bad4fd5/core/hashfuncs.h#L158) returns false )\r\n\r\nI think making a copy of the keys (and values?) is a good solution.\r\n\r\nIf it is not important enough to change or breaks the overall design, a simple warning in the documentation can be of a great help for other developers."}}
{"actor":{"display_login":"alkhimey"}}