Project

General

Profile

Bug #11669

inconsitent behavior of refining frozen class

Added by naruse (Yui NARUSE) over 4 years ago. Updated 5 days ago.

Status:
Assigned
Priority:
Normal
Target version:
-
ruby -v:
ruby 2.3.0dev (2015-10-26 trunk 52291) [x86_64-darwin15]
[ruby-core:71391]
Tags:

Description

Is this expected behavior?

class C
  def foo
    p 1
  end
end
module Foo
  refine C do
    def foo
      p 2
    end
  end
end
using Foo
C.new.foo #=> 2
C.freeze
module Foo
  refine C do
    def foo
      p 3
    end
    def bar #=>  can't modify frozen class (RuntimeError)
      p 3
    end
  end
end
C.new.foo
C.new.bar
ruby 2.3.0dev (2015-10-26 trunk 52291) [x86_64-darwin15]
2
test.rb:21:in `block in <module:Foo>': can't modify frozen class (RuntimeError)
    from test.rb:17:in `refine'
    from test.rb:17:in `<module:Foo>'
    from test.rb:16:in `<main>'

Updated by jeremyevans0 (Jeremy Evans) 5 days ago

Here's the backtrace showing why the frozen error is raised:

#0  rb_class_modify_check (klass=7782713867440) at eval.c:495
#1  0x00000713a3570c14 in rb_method_entry_make (klass=7782713867440, mid=51041, defined_class=7782713867440, visi=METHOD_VISI_PUBLIC, type=VM_METHOD_TYPE_REFINED, def=0x0, original_id=51041, opts=0x0)
    at ./vm_method.c:714
#2  0x00000713a356f598 in rb_add_method (klass=7782713867440, mid=51041, type=VM_METHOD_TYPE_REFINED, opts=0x0, visi=METHOD_VISI_PUBLIC) at ./vm_method.c:831
#3  0x00000713a35708f4 in rb_add_refined_method_entry (refined_class=7782713867440, mid=51041) at ./vm_method.c:655
#4  0x00000713a3570c46 in rb_method_entry_make (klass=7782713865520, mid=51041, defined_class=7782713865520, visi=METHOD_VISI_PUBLIC, type=VM_METHOD_TYPE_ISEQ, def=0x0, original_id=51041, opts=0x7f7ffffcb250)
    at ./vm_method.c:718
#5  0x00000713a356f598 in rb_add_method (klass=7782713865520, mid=51041, type=VM_METHOD_TYPE_ISEQ, opts=0x7f7ffffcb250, visi=METHOD_VISI_PUBLIC) at ./vm_method.c:831
#6  0x00000713a3571370 in rb_add_method_iseq (klass=7782713865520, mid=51041, iseq=0x713ed7001b8, cref=0x7140de521f8, visi=METHOD_VISI_PUBLIC) at ./vm_method.c:848
#7  0x00000713a358afa3 in vm_define_method (ec=0x71432617650, obj=8, id=51041, iseqval=7782169313720, is_singleton=0) at ./vm_insnhelper.c:4036
#8  0x00000713a35670cd in vm_exec_core (ec=0x71432617650, initial=0) at insns.def:756
#9  0x00000713a357fc02 in rb_vm_exec (ec=0x71432617650, mjit_enable_p=1) at vm.c:1936
#10 0x00000713a35a6227 in invoke_block (ec=0x71432617650, iseq=0x713ed7003c0, self=7782713865520, captured=0x7f7ffffcd418, cref=0x7140de521f8, type=572653569, opt_pc=0) at vm.c:1052
#11 0x00000713a35a5e32 in invoke_iseq_block_from_c (ec=0x71432617650, captured=0x7f7ffffcd418, self=7782713865520, argc=0, argv=0x0, kw_splat=0, passed_block_handler=0, cref=0x7140de521f8, is_lambda=0, me=0x0)
    at vm.c:1124
#12 invoke_block_from_c_bh (ec=0x71432617650, block_handler=140187732333593, argc=0, argv=0x0, kw_splat=0, passed_block_handler=0, cref=0x7140de521f8, is_lambda=0, force_blockarg=0) at vm.c:1142
#13 0x00000713a357a3d4 in vm_yield_with_cref (ec=0x71432617650, argc=0, argv=0x0, kw_splat=0, cref=0x7140de521f8, is_lambda=0) at vm.c:1179
#14 0x00000713a357a0f8 in rb_yield_refine_block (refinement=7782713865520, refinements=7782713865720) at ./vm_eval.c:1782
#15 0x00000713a32ea0fc in rb_mod_refine (module=7782713866920, klass=7782713867440) at eval.c:1587

Basically, refined methods modify the method table for the class, which isn't allowed if the class is frozen. If these methods are considered internal, it seems reasonable not to raise in this case. I've added a pull request that implements that: https://github.com/ruby/ruby/pull/3175

Also available in: Atom PDF