You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
instance_variable_set is a silent no-op on File/StringIO/Dir/IO::Buffer/Array/Hash/String/Proc (ivarTable returns nil) #672
instance_variable_set on most of rbgo's natively-backed objects is a silent no-op. It does not raise; the write is discarded and the next read answers nil.
Measured across the natively-backed kinds (instance_variable_set(:@zz, 7) then get):
receiver
MRI 4.0.5
rbgo
File
7
nil
StringIO
7
nil
Dir
7
nil
IO::Buffer
7
nil
Array
7
nil
Hash
7
nil
String
7
nil
Proc
7
nil
Range
FrozenError (a literal Range is frozen)
nil
Time
7
7
Object
7
7
ivarTable (internal/vm/object_model.go) enumerates the kinds that have ivar storage — RObject, RClass, object.Main, SinatraCtx, ActionViewBase, and the boxed method values — and returns nil for everything else. Every caller then has nowhere to write and, apparently, no complaint.
The silence is the dangerous part: attr_accessor on a singleton class of such an object appears to work — the reader and writer are defined and callable — and simply never stores anything.
Measured cost
Two examples in core/file/open_spec.rb, via core/file/fixtures/common.rb's FileSpecs.make_closer:
core/file/open_spec.rb rbgo = 78 MRI 4.0.5 = 82
defself.make_closer(obj,exc=nil)class << objattr_accessor:close_exceptionalias_method:original_close,:closedefcloseoriginal_closeScratchPad << :file_closedraise@close_exceptionif@close_exception# @close_exception is always nil in rbgoendendobj.close_exception=exc# discardedend
So "propagates StandardErrors produced by close" and "propagates non-StandardErrors produced by close" both see no exception. The File.open ensure machinery is correct — ioYieldAndClose already re-raises a #close exception and filters the IOError "closed stream" case, and it is witnessed working when the override raises unconditionally:
File.open(p,"r")do |f|
class << falias_method:oc,:closedefclose;oc;raiseStandardError,"boom";end# this DOES propagate in rbgoendend
The defect is only that the fixture's exception never gets stored.
Given attr_accessor on a singleton is a common spec-fixture idiom, and String/Array/Hash/Proc are on the list too, this very likely costs more than these two examples across the suite.
Suggested shape
Give the natively-backed values an ivar table the way boxed already does — a small embedded struct with a lazily-created map — rather than extending the type switch one kind at a time. Time and the boxed method values already show the pattern.
Meanwhile, a caller that cannot find a table should probably not stay silent.
Where
internal/vm/object_model.go (ivarTable) and internal/object. Both outside the file set of #668, which is why this is filed rather than fixed there.
instance_variable_set on the native kinds now works, matching MRI 4.0.5:
s="abc";s.instance_variable_set(:@x,1)s.instance_variable_get(:@x)# 1 (both)s.instance_variables# [:@x] (both)[].instance_variable_set(:@y,2)# reads back 2 (both){}.instance_variable_set(:@z,3)# reads back 3 (both)
core/string/scrub_spec.rb is at its measured ceiling (24/24). Landed in #674
("every object carries an ivar table").
Recorded because it cost time twice today: this issue was routed as a live defect
by two separate agents whose baselines predated #674, and each attributed further
examples to it that belong to other causes. An open issue here is not reliably an
unfinished one — reproduce before building on one.
Activity
wave 33: benchmarks for the ivar paths #672 touches
wave 33: an ivar re-assigned after remove_instance_variable appears o…
wave 33 (object model): every object carries an ivar table (#672), an…
tannevaled commentedon Sep 26, 2026
Fixed and verifiable on
main@8f2a019. Closing.instance_variable_seton the native kinds now works, matching MRI 4.0.5:core/string/scrub_spec.rbis at its measured ceiling (24/24). Landed in #674("every object carries an ivar table").
Recorded because it cost time twice today: this issue was routed as a live defect
by two separate agents whose baselines predated #674, and each attributed further
examples to it that belong to other causes. An open issue here is not reliably an
unfinished one — reproduce before building on one.
internal/vm: Marshal carries the instance variables of String, Array,…