mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix inconsistency with opt_aref_with
opt_aref_with is an optimized instruction for accessing a Hash using a non-frozen string key (ie. from a file without frozen_string_literal). It attempts to avoid allocating the string, and instead silently using a frozen string (hash string keys are always fstrings). Because this is just an optimization, it should be invisible to the user. However, previously this optimization was could be seen via hashes with default procs. For example, previously: h = Hash.new { |h, k| k.frozen? } str = "foo" h[str] # false h["foo"] # true when optimizations enabled This commit checks that the Hash doesn't have a default proc when using opt_aref_with.
This commit is contained in:
parent
1e7a2415a4
commit
70b60d24b9
Notes:
git
2022-08-05 06:49:07 +09:00
2 changed files with 16 additions and 1 deletions
|
@ -304,6 +304,20 @@ class TestHash < Test::Unit::TestCase
|
|||
assert_equal before, ObjectSpace.count_objects[:T_STRING]
|
||||
end
|
||||
|
||||
def test_AREF_fstring_key_default_proc
|
||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||
begin;
|
||||
h = Hash.new do |h, k|
|
||||
k.frozen?
|
||||
end
|
||||
|
||||
str = "foo"
|
||||
refute str.frozen? # assumes this file is frozen_string_literal: false
|
||||
refute h[str]
|
||||
refute h["foo"]
|
||||
end;
|
||||
end
|
||||
|
||||
def test_ASET_fstring_key
|
||||
a, b = {}, {}
|
||||
assert_equal 1, a["abc"] = 1
|
||||
|
|
|
@ -5458,7 +5458,8 @@ vm_opt_aref_with(VALUE recv, VALUE key)
|
|||
{
|
||||
if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash &&
|
||||
BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG) &&
|
||||
rb_hash_compare_by_id_p(recv) == Qfalse) {
|
||||
rb_hash_compare_by_id_p(recv) == Qfalse &&
|
||||
!FL_TEST(recv, RHASH_PROC_DEFAULT)) {
|
||||
return rb_hash_aref(recv, key);
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Reference in a new issue