diff --git a/ChangeLog b/ChangeLog index f860fa1881..762dffe745 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Sep 23 15:47:04 2016 Nobuyoshi Nakada + + * lib/forwardable.rb (_delegator_method): allow private methods to + be delegated, with warnings. [ruby-core:77341] [Bug #12782] + Fri Sep 23 12:15:29 2016 Nobuyoshi Nakada * compile.c (iseq_peephole_optimize): enable tail call diff --git a/lib/forwardable.rb b/lib/forwardable.rb index aa45d41a31..ba8452f695 100644 --- a/lib/forwardable.rb +++ b/lib/forwardable.rb @@ -195,31 +195,42 @@ module Forwardable accessor = "#{accessor}()" end - unless begin - iseq = RubyVM::InstructionSequence - .compile("().#{method}", nil, nil, 0, false) - rescue SyntaxError - else - iseq.to_a.dig(-1, 1, 1, :mid) == method.to_sym - end - method_call = "__send__(:#{method}, *args, &block)" - else - method_call = "#{method}(*args, &block)" + vm = RubyVM::InstructionSequence + method_call = ".__send__(:#{method}, *args, &block)" + if begin + iseq = vm.compile("().#{method}", nil, nil, 0, false) + rescue SyntaxError + else + iseq.to_a.dig(-1, 1, 1, :mid) == method.to_sym + end + loc, = caller_locations(2,1) + pre = "_ =" + mesg = "#{Module === obj ? obj : obj.class}\##{ali} at #{loc.path}:#{loc.lineno} forwarding to private method " + method_call = "#{<<-"begin;"}\n#{<<-"end;".chomp}" + begin; + unless ::Kernel.instance_method(:respond_to?).bind(_).call(:"#{method}") + ::Kernel.warn "\#{caller_locations(1)[0]}: "#{mesg.dump}"\#{_.class}"'##{method}' + _#{method_call} + else + _.#{method}(*args, &block) + end + end; end line_no = __LINE__+1; str = "#{<<-"begin;"}\n#{<<-"end;"}" begin; proc do def #{ali}(*args, &block) + #{pre} begin #{accessor} - end.#{method_call} + end#{method_call} end end end; - RubyVM::InstructionSequence - .compile(str, __FILE__, __FILE__, line_no, + puts str + vm.compile(str, __FILE__, __FILE__, line_no, trace_instruction: false, tailcall_optimization: true) .eval