Bug #21718
closedTypeError:wrong argument type ... (expected Array)
Added by vo.x (Vit Ondruch) about 13 hours ago. Updated about 6 hours ago.
Description
Testing Ruby 4.0 on Fedora, we observe these errors in MiniMagick
1) MiniMagick::Image#composite yields an optional block
Failure/Error: yield composite if block_given?
TypeError:
wrong argument type MiniMagick::Tool (expected Array)
# ./lib/mini_magick/image.rb:515:in 'block in MiniMagick::Image#composite'
# ./lib/mini_magick/tool.rb:34:in 'MiniMagick::Tool.new'
# ./lib/mini_magick.rb:28:in 'block (2 levels) in module:MiniMagick'
# ./lib/mini_magick/image.rb:514:in 'MiniMagick::Image#composite'
# ./spec/lib/mini_magick/image_spec.rb:609:in 'block (4 levels) in <top (required)>'
# ./spec/lib/mini_magick/image_spec.rb:610:in 'block (3 levels) in <top (required)>'
and Vagrant / vagrant-libvirt
340) VagrantPlugins::ProviderLibvirt::Util::NetworkUtil #libvirt_networks should retrieve the list of networks
Failure/Error: let(:machine) { iso_env.machine(:test, :libvirt) }
TypeError:
wrong argument type Vagrant::Config::V2::DummyConfig (expected Array)
# /usr/share/vagrant/gems/gems/vagrant-2.3.4/plugins/kernel_v2/config/vm.rb:713:in 'Kernel#inspect'
# /usr/share/vagrant/gems/gems/vagrant-2.3.4/plugins/kernel_v2/config/vm.rb:713:in 'VagrantPlugins::Kernel_V2::VMConfig#get_provider_config'
# /usr/share/vagrant/gems/gems/vagrant-2.3.4/lib/vagrant/vagrantfile.rb:75:in 'Vagrant::Vagrantfile#machine'
# /usr/share/vagrant/gems/gems/vagrant-2.3.4/lib/vagrant/environment.rb:740:in 'Vagrant::Environment#machine'
# ./spec/support/unit_context.rb:26:in 'block (2 levels) in <top (required)>'
# ./spec/support/unit_context.rb:37:in 'block (2 levels) in <top (required)>'
# ./spec/support/unit_context.rb:51:in 'block (3 levels) in <top (required)>'
# ./spec/support/unit_context.rb:43:in 'block (2 levels) in <top (required)>'
# /usr/share/rubygems/rubygems.rb:303:in 'Kernel#load'
# /usr/share/rubygems/rubygems.rb:303:in 'Gem.activate_and_load_bin_path'
Trying to investigate closer the vagrant-libvirt case, I really cannot wrap my head around it, because it fails with innocently looking result.inspect 1. The image_magick fails at yield composite if block_given? line, so I suspect that the yield composite is the specific place.
Since this does not make any sense to me, I have grepped the Ruby source code for:
$ grep -R -e TypeError | grep "wrong argument type.*Array"
... snip ...
prism/extension.c: rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(scopes));
prism/extension.c: rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(locals));
prism/extension.c: rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(names));
This seems to come from https://github.com/ruby/prism/commit/21abb6b7c499b41a951eba7c8219c336a656da40 . So is it the reason? Not sure.
Updated by Earlopain (Earlopain _) about 12 hours ago
ยท Edited
Actions
#1
[ruby-core:123932]
I only checked minimagick, this looks caused by https://bugs.ruby-lang.org/issues/21219
MiniMagick::Tool defines method_missing and returns itself: https://github.com/minimagick/minimagick/blob/ddcbfe9632667876be10373e1e01252617e74057/lib/mini_magick/tool.rb#L257-L262
The test passes if I explicitly return an array on like return [] if name == :instance_variables_to_inspect. Rspec code is not comprehensible to me but it looks like it might use inspect to match yielded arguments or something along those lines?
Basically, it boils down to this:
class Foo
def method_missing(...)
self
end
end
Foo.new.inspect # 'Kernel#inspect': wrong argument type Foo (expected Array) (TypeError)
Even just calling method_missing would break minimagick tests, so practically you would also always need to implement instance_variables_to_inspect for correctness or risk being broken by inspect. So not raising on unexpected types in inspect would not really help and just move the error someplace else. Skipping method_missing for instance_variables_to_inspect (needing it to be explicitly defined) could work but seems a bit unexpected?
Updated by mtasaka (Mamoru TASAKA) about 11 hours ago
Actions
#2
[ruby-core:123933]
it looks like it might use inspect to match yielded arguments or something along those lines?
Maybe to_s calls inspect?
Updated by vo.x (Vit Ondruch) about 10 hours ago
Actions
#3
[ruby-core:123934]
I only checked minimagick, this looks caused by https://bugs.ruby-lang.org/issues/21219
Yep, I think so.
I have just tried to add p composite on this place and this seems to be the BT where it gets wrong:
(gdb) call (void) rb_backtrace()
from /usr/bin/rspec:25:in '<main>'
from /usr/bin/rspec:25:in 'load'
from /usr/share/gems/gems/rspec-core-3.13.6/exe/rspec:4:in '<top (required)>'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:45:in 'invoke'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:71:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:89:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:115:in 'run_specs'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/reporter.rb:74:in 'report'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:116:in 'block in run_specs'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/configuration.rb:2097:in 'with_suite_hooks'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:121:in 'block (2 levels) in run_specs'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:121:in 'map'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/runner.rb:121:in 'block (3 levels) in run_specs'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:615:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:615:in 'map'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:615:in 'block in run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:614:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:649:in 'run_examples'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:649:in 'map'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example_group.rb:653:in 'block in run_examples'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:259:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:511:in 'with_around_and_singleton_context_hooks'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:468:in 'with_around_example_hooks'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/hooks.rb:486:in 'run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/hooks.rb:624:in 'run_around_example_hooks_for'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/hooks.rb:486:in 'block in run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:468:in 'block in with_around_example_hooks'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:511:in 'block in with_around_and_singleton_context_hooks'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:263:in 'block in run'
from /usr/share/gems/gems/rspec-core-3.13.6/lib/rspec/core/example.rb:263:in 'instance_exec'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/spec/lib/mini_magick/image_spec.rb:610:in 'block (3 levels) in <top (required)>'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/expectations/expectation_target.rb:139:in 'to'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/expectations/expectation_target.rb:65:in 'to'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/expectations/handler.rb:47:in 'handle_matcher'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/expectations/handler.rb:26:in 'with_matcher'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/expectations/handler.rb:50:in 'block in handle_matcher'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/matchers/built_in/yield.rb:213:in 'matches?'
from /usr/share/gems/gems/rspec-expectations-3.13.5/lib/rspec/matchers/built_in/yield.rb:35:in 'probe'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/spec/lib/mini_magick/image_spec.rb:609:in 'block (4 levels) in <top (required)>'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick/image.rb:514:in 'composite'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick.rb:28:in 'block (2 levels) in <module:MiniMagick>'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick/tool.rb:34:in 'new'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick/image.rb:516:in 'block in composite'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick/image.rb:516:in 'p'
from /builddir/build/BUILD/rubygem-mini_magick-5.3.1-build/mini_magick-5.3.1/usr/share/gems/gems/mini_magick-5.3.1/lib/mini_magick/image.rb:516:in 'inspect'
(gdb) bt
#0 ruby__sfvextra (fp=0x7fffffffc480, valsize=<optimized out>, valp=0x7fffffffbe18, sz=0x7fffffffbe20, sign=0) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/sprintf.c:1125
#1 0x00007ffff7a0ff19 in BSD_vfprintf (fp=fp@entry=0x7fffffffc480, fmt0=fmt0@entry=0x7ffff7c65a10 "wrong argument type %li\v (expected %s)", ap=ap@entry=0x7fffffffc540)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vsnprintf.c:830
#2 0x00007ffff7a1172a in ruby_vsprintf0 (result=result@entry=140737340003120, p=0x7ffff7285348 "wrong argument type ", fmt=fmt@entry=0x7ffff7c65a10 "wrong argument type %li\v (expected %s)",
ap=ap@entry=0x7fffffffc540) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/sprintf.c:1164
#3 0x00007ffff7a11829 in rb_enc_vsprintf (enc=enc@entry=0x0, fmt=0x7ffff7c65a10 "wrong argument type %li\v (expected %s)", ap=ap@entry=0x7fffffffc540)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/include/ruby/internal/core/rstring.h:397
#4 0x00007ffff7a11931 in rb_vsprintf (fmt=<optimized out>, ap=ap@entry=0x7fffffffc540) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/sprintf.c:1213
#5 0x00007ffff7a119e1 in rb_sprintf (format=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/sprintf.c:1223
#6 0x00007ffff7808dfc in unexpected_type (x=x@entry=140736882595640, xt=<optimized out>, t=t@entry=7) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/error.c:1322
#7 0x00007ffff7808e9b in rb_unexpected_type (x=140736882595640, t=7) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/error.c:1366
#8 0x00007ffff780ada5 in Check_Type (v=<optimized out>, t=RUBY_T_ARRAY) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/include/ruby/internal/value_type.h:447
#9 rb_obj_inspect (obj=140736882595640) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/object.c:862
#10 0x00007ffff7a9d570 in vm_call0_cfunc_with_frame (ec=0x555555561080, calling=<optimized out>, argv=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:164
#11 vm_call0_cfunc (ec=0x555555561080, calling=<optimized out>, argv=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:178
#12 vm_call0_body (ec=0x555555561080, calling=<optimized out>, argv=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:229
#13 0x00007ffff7aa18aa in vm_call0_cc (ec=0x555555561080, recv=140736882595640, id=2801, argc=0, argv=<optimized out>, cc=<optimized out>, kw_splat=0)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:101
#14 rb_funcallv_scope (recv=140736882595640, mid=2801, argc=0, argv=<optimized out>, scope=CALL_FCALL) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:1065
#15 rb_funcallv (recv=140736882595640, mid=2801, argc=0, argv=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:1080
#16 0x00007ffff7961509 in rb_inspect (obj=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/object.c:748
#17 0x00007ffff791851c in rb_f_p (argc=1, argv=0x7ffff73f8760, self=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/io.c:9093
#18 0x00007ffff7a8669e in vm_call_cfunc_with_frame_ (ec=0x555555561080, reg_cfp=0x7ffff74f7670, calling=<optimized out>, argc=1, argv=<optimized out>, stack_bottom=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_insnhelper.c:3915
#19 0x00007ffff7a90095 in vm_sendish (ec=<optimized out>, reg_cfp=<optimized out>, cd=<optimized out>, block_handler=<optimized out>, method_explorer=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_insnhelper.c:6134
#20 vm_exec_core (ec=0x7ffff72bf468) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/redhat-linux-build/insns.def:902
#21 0x00007ffff7aa7a5f in vm_exec_loop (ec=<optimized out>, state=<optimized out>, tag=<optimized out>, result=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:2811
#22 rb_vm_exec (ec=0x555555561080) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:2787
#23 0x00007ffff7aaa730 in vm_yield_with_cref (ec=0x555555561080, argc=1, argv=0x7ffff73f84d8, kw_splat=0, cref=<optimized out>, is_lambda=0)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:1865
#24 yield_under (self=<optimized out>, singleton=<optimized out>, argc=1, argv=0x7ffff73f84d8, kw_splat=0) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:2218
#25 0x00007ffff7a8669e in vm_call_cfunc_with_frame_ (ec=0x555555561080, reg_cfp=0x7ffff74f7980, calling=<optimized out>, argc=1, argv=<optimized out>, stack_bottom=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_insnhelper.c:3915
#26 0x00007ffff7a8c1c8 in vm_sendish (ec=<optimized out>, reg_cfp=<optimized out>, cd=<optimized out>, block_handler=<optimized out>, method_explorer=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_callinfo.h:437
#27 0x00007ffff7a90af2 in vm_exec_core (ec=0x7ffff72bf468) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/redhat-linux-build/insns.def:854
#28 0x00007ffff7aa7a5f in vm_exec_loop (ec=<optimized out>, state=<optimized out>, tag=<optimized out>, result=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:2811
#29 rb_vm_exec (ec=0x555555561080) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:2787
#30 0x00007ffff7aaad3f in vm_yield_with_cref (ec=<optimized out>, argc=1, argv=0x7fffffffd078, kw_splat=0, cref=0x0, is_lambda=0)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:1865
#31 vm_yield (ec=<optimized out>, argc=1, argv=0x7fffffffd078, kw_splat=0) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm.c:1873
#32 rb_yield_0 (argc=1, argv=0x7fffffffd078) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:1362
#33 rb_yield (val=<optimized out>) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_eval.c:1378
#34 0x00007ffff7820c4d in rb_ary_collect (ary=140736883800480) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/array.c:3673
#35 0x00007ffff7a8669e in vm_call_cfunc_with_frame_ (ec=0x555555561080, reg_cfp=0x7ffff74f7be8, calling=<optimized out>, argc=0, argv=<optimized out>, stack_bottom=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_insnhelper.c:3915
#36 0x00007ffff7a8c1c8 in vm_sendish (ec=<optimized out>, reg_cfp=<optimized out>, cd=<optimized out>, block_handler=<optimized out>, method_explorer=<optimized out>)
at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/vm_callinfo.h:437
#37 0x00007ffff7a90af2 in vm_exec_core (ec=0x7ffff72bf468) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/redhat-linux-build/insns.def:854
#38 0x00007ffff7aa7a5f in vm_exec_loop (ec=<optimized out>, state=<optimized out>, tag=<optimized out>, result=<optimized out>)
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) f 9
#9 rb_obj_inspect (obj=140736882595640) at /usr/src/debug/ruby-4.0.0~20251118.0917git85abc59c32-28.fc44.251118.07.x86_64/object.c:862
862 Check_Type(ivars, T_ARRAY);
Updated by vo.x (Vit Ondruch) about 9 hours ago
Actions
#4
[ruby-core:123935]
To me, it seems that the VALUE ivars = rb_check_funcall(obj, id_instance_variables_to_inspect, 0, 0); code at rb_obj_inspect assumes that there is returned either nil or Array of symbols. But with method_missing available, it can essentially return anything and in the case of MiniMagick, there is returned MiniMagick::Tool (it could even be array of something else then symbols, what would happen in such case?).
IOW it seems that this feature implies that whenever method_missing is defined, it needs to take care about instance_variables_to_inspect. But that does not sound reasonable behavior to me.
Updated by vo.x (Vit Ondruch) about 9 hours ago
Actions
#5
[ruby-core:123936]
This is essentially what happens:
$ irb
irb(main):001* class Foo
irb(main):002* def initialize
irb(main):003* @bar = "bar"
irb(main):004* end
irb(main):005> end
=> :initialize
irb(main):006> Foo.new.inspect
=> "#<Foo:0x00007fe55b5f7c18 @bar=\"bar\">"
irb(main):007* class Foo
irb(main):008* def instance_variables_to_inspect = Object.new
irb(main):009> end
=> :instance_variables_to_inspect
irb(main):010> Foo.new.inspect
(irb):10:in 'Kernel#inspect': wrong argument type Object (expected Array) (TypeError)
from (irb):10:in '<main>'
from /usr/share/gems/gems/irb-1.14.3/exe/irb:9:in '<top (required)>'
from /usr/bin/irb:25:in 'Kernel#load'
from /usr/bin/irb:25:in '<main>'
But if the method_missing should somehow treat the nonexistence of instance_variables_to_inspect is also interesting question
Updated by luke-gru (Luke Gruber) about 8 hours ago
Actions
#6
[ruby-core:123937]
Ignoring method_missing in this case or wrapping the non-array object in an array are the only workarounds I can think of. I don't believe ruby ever ignores method_missing like this, so it would be a bit different to do it here.
Updated by byroot (Jean Boussier) about 8 hours ago
Actions
#7
[ruby-core:123938]
I agree we shouldn't fallback to method_missing when checking for instance_variables_to_inspect. Not fully sure how to do that though.
Updated by vo.x (Vit Ondruch) about 8 hours ago
Actions
#8
[ruby-core:123939]
In retrospect, is the instance_variables_to_inspect design good? Wouldn't it be better if such method behaved as some filter? E.g. it would get e.g. an array of something (maybe list of instance variables?), which could be altered and returned afterwards? And maybe such method should be always defined, to prevent surprises with method_missing? Just thinking loud ...
Updated by byroot (Jean Boussier) about 8 hours ago
Actions
#9
[ruby-core:123940]
- Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONTNEED
I think the better solution here is to pre-define Kernel#instance_variables_to_inspect https://github.com/ruby/ruby/pull/15345
Updated by vo.x (Vit Ondruch) about 7 hours ago
Actions
#10
[ruby-core:123941]
byroot (Jean Boussier) wrote in #note-9:
I think the better solution here is to pre-define
Kernel#instance_variables_to_inspect
That solves one part. But if this is considered acceptable, could the error message (and/or documentation) be improved to provide more context? And I have not tried what would happen if the array returned by instance_variables_to_inspect contained some garbage ...
Updated by byroot (Jean Boussier) about 6 hours ago
Actions
#11
[ruby-core:123942]
could the error message (and/or documentation) be improved to provide more context?
Yes, I'll work on that. the standard Check_Type helper was used, but since it's not clear where the failing type is common from..
I have not tried what would happen if the array returned by instance_variables_to_inspect contained some garbage ...
That has been speced in the original commit.
Updated by vo.x (Vit Ondruch) about 6 hours ago
Actions
#12
[ruby-core:123943]
vo.x (Vit Ondruch) wrote in #note-10:
And I have not tried what would happen if the array returned by
instance_variables_to_inspectcontained some garbage ...
Just tested a few examples:
$ irb
irb(main):001* class Foo
irb(main):002* def initialize
irb(main):003* @bar = "bar"
irb(main):004* end
irb(main):005> end
=> :initialize
irb(main):006> Foo.new.inspect
=> "#<Foo:0x00007f2fda17a460 @bar=\"bar\">"
irb(main):007* class Foo
irb(main):008* def instance_variables_to_inspect = [Object.new]
irb(main):009> end
=> :instance_variables_to_inspect
irb(main):010> Foo.new.inspect
=> "#<Foo:0x00007f2fd9ffbc88>"
irb(main):011* class Foo
irb(main):012* def instance_variables_to_inspect = [:bar]
irb(main):013> end
=> :instance_variables_to_inspect
irb(main):014> Foo.new.inspect
=> "#<Foo:0x00007f2fda2d19d0>"
irb(main):015* class Foo
irb(main):016* def instance_variables_to_inspect = [:@bar]
irb(main):017> end
=> :instance_variables_to_inspect
irb(main):018> Foo.new.inspect
=> "#<Foo:0x00007f2fd9e593f8 @bar=\"bar\">"
irb(main):019* class Foo
irb(main):020* def instance_variables_to_inspect = [nil]
irb(main):021> end
=> :instance_variables_to_inspect
irb(main):022> Foo.new.inspect
=> "#<Foo:0x00007f2fda20c568>"
irb(main):023* class Foo
irb(main):024* def instance_variables_to_inspect = nil
irb(main):025> end
=> :instance_variables_to_inspect
irb(main):026> Foo.new.inspect
=> "#<Foo:0x00007f2fd9c21748>"
irb(main):027> Foo.undef_method :instance_variables_to_inspect
=> Foo
irb(main):028> Foo.new.inspect
=> "#<Foo:0x00007f2fda11b758 @bar=\"bar\">"
irb(main):029>
Updated by byroot (Jean Boussier) about 6 hours ago
Actions
#13
- Related to Feature #21219: `Object#inspect` accept a list of instance variables to display added
Updated by byroot (Jean Boussier) about 6 hours ago
Actions
#14
- Status changed from Open to Closed
Applied in changeset git|191bfcb9c505ba3f5771f7ac67d6131aeb6b6837.
Define Kernel#instance_variables_to_inspect
[Bug #21718]
Otherwise objects that don't define it, but define a fairly liberal
method_missing method will run into errors that are hard to understand:
class Foo
def method_missing(name, ...)
name
end
end
p Foo.new.inspect
'Kernel#inspect': wrong argument type Symbol (expected Array) (TypeError)
from ../test.rb:7:in '<main>'