[ruby-core:116965] [Ruby master Bug#20307] `Hash#update` from compare_by_identity hash can have unfrozen string keys

Issue #20307 has been reported by nobu (Nobuyoshi Nakada). ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307 * Author: nobu (Nobuyoshi Nakada) * Status: Open * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h["a"] # => 0 k.upcase! p h.fetch(k) # in 'Hash#fetch': key not found: "A" (KeyError) ``` -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by nobu (Nobuyoshi Nakada). Description updated https://github.com/ruby/ruby/pull/10099 ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-107013 * Author: nobu (Nobuyoshi Nakada) * Status: Open * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by Dan0042 (Daniel DeLorme). After the code above, we can do ```ruby h.rehash p h #=> {"A"=>1} ``` When a key is clobbered like that due to a rehash, maybe there should be a warning or an error? It seems to me a pretty clear sign of a bug, either in the ruby code or in the interpreter itself. ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-107114 * Author: nobu (Nobuyoshi Nakada) * Status: Open * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by byroot (Jean Boussier). I don't understand the bug report nor the patch. If you make a frozen copy of the provided key, you change the key. e.g. ``` cache = {}.compare_by_indentity key = Random.bytes(5) cache[key] = 1 p cache[key] ``` I'd expect `cache[key]` to return `1`, with what I understand of your patch, it wouldn't anymore. Mutable hash keys aren't a new thing, it's only that regular hash have this special behavior for strings to keep a frozen copy of the string key, but they don't do that for any other type. I don't see why identity hashes would need to copy this behavior. ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-107115 * Author: nobu (Nobuyoshi Nakada) * Status: Open * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by byroot (Jean Boussier). ignore me, I misunderstood the reproduction script. `h` is not compared by identity. ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-107116 * Author: nobu (Nobuyoshi Nakada) * Status: Open * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by k0kubun (Takashi Kokubun). Backport changed from 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: REQUIRED to 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: DONE ruby_3_3 commit:917f3e5d22b3364002eb1fdc2f94b35ff76f6a73 merged revision(s) commit:f36a71e26995b69ff72bc132bbcf40ad89571414. ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-108474 * Author: nobu (Nobuyoshi Nakada) * Status: Closed * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: DONE ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/

Issue #20307 has been updated by nagachika (Tomoyuki Chikanaga). Backport changed from 3.0: REQUIRED, 3.1: REQUIRED, 3.2: REQUIRED, 3.3: DONE to 3.0: REQUIRED, 3.1: REQUIRED, 3.2: DONE, 3.3: DONE ruby_3_2 commit:90a44bcd39c569d851f73d167955c83f3ff2384f merged revision(s) commit:f36a71e26995b69ff72bc132bbcf40ad89571414. ---------------------------------------- Bug #20307: `Hash#update` from compare_by_identity hash can have unfrozen string keys https://bugs.ruby-lang.org/issues/20307#change-109112 * Author: nobu (Nobuyoshi Nakada) * Status: Closed * Backport: 3.0: REQUIRED, 3.1: REQUIRED, 3.2: DONE, 3.3: DONE ---------------------------------------- I don't think this behavior is expected. ```ruby i = Hash.new.compare_by_identity k = "a" i[k] = 0 h = {}.update(i) p h.compare_by_identity? # => false p h["a"] # => 0 k.upcase! # `k` is still in `h`. p h.keys.include?(k) # => true # but not found. p((h.fetch(k) rescue $!)) # => #<KeyError: key not found: "A"> h["A"] = 1 p h # => {"A"=>0, "A"=>1} ``` I expect `h` to still have `"a"=>0` entry. -- https://bugs.ruby-lang.org/
participants (5)
-
byroot (Jean Boussier)
-
Dan0042 (Daniel DeLorme)
-
k0kubun (Takashi Kokubun)
-
nagachika (Tomoyuki Chikanaga)
-
nobu (Nobuyoshi Nakada)