From: shevegen@... Date: 2018-09-14T09:44:51+00:00 Subject: [ruby-core:89005] [Ruby trunk Bug#15118] Method [] does not respect frozen_string_literal: true comment Issue #15118 has been updated by shevegen (Robert A. Heiler). Interesting. I just tested with this code: #!/System/Index/bin/ruby -w # Encoding: ISO-8859-1 # frozen_string_literal: true # =========================================================================== # NopProc = proc {|a| a } def foobar result = NopProc["sometext"] result end x = foobar puts x.class puts x.frozen? y = 'abc' puts y.frozen? # Result: # String # false # true And I think you are right. I am testing .frozen? twice; the 'abc' string is indeed frozen whereas the variant returned by [] does not seem to honour the instruction in the "magic" comment section. Very good catch. May I ask, for curiosity, how you discovered it? I assume you may have tested somehow systematically or something? ---------------------------------------- Bug #15118: Method [] does not respect frozen_string_literal: true comment https://bugs.ruby-lang.org/issues/15118#change-74033 * Author: chopraanmol1 (Anmol Chopra) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.6.0dev (2018-09-13 trunk 64736) [x86_64-linux] * Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN ---------------------------------------- Calling ["something"] on object or proc (non-hash aref implementation) does not respect frozen_string_literal: true comment **Script:** ~~~ # frozen_string_literal: true require 'benchmark' require 'memory_profiler' class NopId def self.[](str) str.__id__ end end SampleHash = {"sometext" => 0} NopProc = proc{|a| a.__id__} N = 1_000_000 def method1 NopId["sometext"] end def method2 SampleHash["sometext"] end def method3 NopProc["sometext"] end def print_iseq method_name puts "-+"*20 puts RubyVM::InstructionSequence.disasm method(method_name) puts "-+"*20 end def print_memory_profiler title, &block puts "-+"*20 puts title MemoryProfiler.report{N.times(&block)}.pretty_print(detailed_report: false, allocated_strings: 0, retained_strings: 0) puts "-+"*20 end print_iseq :method1 print_iseq :method2 print_iseq :method3 Benchmark.bm(10) do |bm| bm.report("method[]"){ N.times{ method1 } } bm.report("hash[]"){ N.times{ method2 } } bm.report("proc[]"){ N.times{ method3 } } end print_memory_profiler("method[]"){method1} print_memory_profiler("hash[]"){method2} print_memory_profiler("proc[]"){method3} ~~~ **Output:** ~~~ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 18)[LiCa] 0003 getconstant :NopId 0005 setinlinecache 0007 opt_aref_with "sometext", , 0011 leave ( 19)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 22)[LiCa] 0003 getconstant :SampleHash 0005 setinlinecache 0007 opt_aref_with "sometext", , 0011 leave ( 23)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 26)[LiCa] 0003 getconstant :NopProc 0005 setinlinecache 0007 opt_aref_with "sometext", , 0011 leave ( 27)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ user system total real method[] 0.120000 0.000000 0.120000 ( 0.121639) hash[] 0.088000 0.000000 0.088000 ( 0.089411) proc[] 0.136000 0.000000 0.136000 ( 0.133279) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ method[] Total allocated: 40000000 bytes (1000000 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ hash[] Total allocated: 0 bytes (0 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ proc[] Total allocated: 40000000 bytes (1000000 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ As you can observe calling NopClass["something"] & NopProc["something"] doesnot respect frozen_string_literal: true comment **Patch:** **https://github.com/ruby/ruby/pull/1957** **After Patch Result:** ~~~ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 18)[LiCa] 0003 getconstant :NopId 0005 setinlinecache 0007 putobject "sometext" 0009 opt_aref , 0012 leave ( 19)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 22)[LiCa] 0003 getconstant :SampleHash 0005 setinlinecache 0007 putobject "sometext" 0009 opt_aref , 0012 leave ( 23)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ == disasm: # (catch: FALSE) 0000 getinlinecache 7, ( 26)[LiCa] 0003 getconstant :NopProc 0005 setinlinecache 0007 putobject "sometext" 0009 opt_aref , 0012 leave ( 27)[Re] -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ user system total real method[] 0.100000 0.004000 0.104000 ( 0.100786) hash[] 0.088000 0.000000 0.088000 ( 0.089176) proc[] 0.108000 0.000000 0.108000 ( 0.107366) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ method[] Total allocated: 0 bytes (0 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ hash[] Total allocated: 0 bytes (0 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ proc[] Total allocated: 0 bytes (0 objects) Total retained: 0 bytes (0 objects) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ -- https://bugs.ruby-lang.org/ Unsubscribe: