From: nobu@... Date: 2016-05-04T08:57:36+00:00 Subject: [ruby-core:75347] [Ruby trunk Bug#12344][Rejected] check_funcall_respond_to behavior seems incorrect Issue #12344 has been updated by Nobuyoshi Nakada. Description updated Status changed from Open to Rejected It's a common mistake, to define `method_missing` but not `respond_to_missing?`. ---------------------------------------- Bug #12344: check_funcall_respond_to behavior seems incorrect https://bugs.ruby-lang.org/issues/12344#change-58475 * Author: Matt Bedalov * Status: Rejected * Priority: Normal * Assignee: * ruby -v: ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux] * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- Prior to ruby 2.3, and specifically I believe prior to the implementation of this change: > Thu Aug 20 14:13:27 2015 Nobuyoshi Nakada > vm_eval.c (check_funcall_respond_to) > share the behavior with rb_obj_respond_to. [ruby-core:70460] [Bug #11465] > > vm_method.c (vm_respond_to) > extract from rb_obj_respond_to and merge r39881. When a global method_missing was defined, I believe that "`check_funcall_respond_to`" would not yield that the `to_hash` method would be defined for objects of type `String`. In Ruby 2.3, it behaves as if `to_hash` is defined on a `String` just due to the fact that we've added a global `method_missing`. This is hugely problematic when calling a gsub as the second parameter is checked (in `str_gsub` - string.c:4593) to see if it will act like a hash - i.e. is it a `Hash` or does it have a `to_hash` method. It appears that eventually `vm_respond_to()` calls `METHOD_ENTRY_BASIC()` which then makes the false statement that the object responds to the `to_hash` method. I believe that a possible fix is to have vm_eval.c - `check_funcall_respond_to` be changed from: ~~~c static int check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid) { return vm_respond_to(th, klass, recv, mid, TRUE); } ~~~ **to**: ~~~c static int check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid) { return rb_obj_respond_to(recv, mid, TRUE); } ~~~ With the current behavior, the following in my opinion is incorrectly throwing the `NameError` in the `method_missing`. ~~~ruby def method_missing(name, *args, &block) raise NameError, "#{name} not defined on #{self.inspect}" end puts "foo".gsub(/o/, "bar") ~~~ -- https://bugs.ruby-lang.org/ Unsubscribe: