Bug #13592
closedEnumerable#reduce with symbol does not respect method visibility
Description
When use reduce with symbol, I expect the symbol is called in object but respecting the method visibility.
Example with source code written in a file.
Fixnum.instance_eval do
private :+
end
p [1,2,3].reduce(:+)
The behavior in IRB is different.
irb(main):001:0> [1,2,3].reduce(:+)
=> 6
irb(main):002:0> Fixnum.instance_eval do
irb(main):003:1* private :+
irb(main):004:1> end
=> Fixnum
irb(main):005:0>
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/irb/input-method.rb:154:in `gets': private method `+' called for 4:Fixnum (NoMethodError)
Now, I am confused. Those behaviors are expected? In doc this is not clear.
Updated by americodls (Americo Duarte) over 7 years ago
Sorry, ignore the IRB thing. But my question about the reduce still valid.
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
- Description updated (diff)
- Status changed from Open to Rejected
The proc returned by Symbol#to_proc
is equivalent to proc {|recv, *args| recv.__send__(self, *args)}
.
So it can call private methods too.
Updated by americodls (Americo Duarte) over 7 years ago
- Status changed from Rejected to Feedback
Please, reconsider. Look this example:
irb(main):092:0> :puts.to_proc.call("")
NoMethodError: private method `puts' called for "":String
nobu (Nobuyoshi Nakada) wrote:
The proc returned by
Symbol#to_proc
is equivalent toproc {|recv, *args| recv.__send__(self, *args)}
.
So it can call private methods too.
Updated by americodls (Americo Duarte) over 7 years ago
- Status changed from Feedback to Open
Updated by Hanmac (Hans Mackowiak) over 7 years ago
reduce(&:+) is different from
reduce(:+), this one has nothing to do with :+.to_proc
reduce/inject with symbol param does call the method internally without checking if its private or not
Updated by americodls (Americo Duarte) over 7 years ago
This is exactly what I am saying.
This behavior of reduce
is unpredictable and different of the another Enumerable
methods.
Users will expect that symbol argument is converted in proc and then applied to object.
reduce
(since v1.8.7) is older than public_send
(since 1.9.1), maybe this is the reason of the reduce
works like that.
But these days, as we have public_send
and the :symbol.to_proc
works similar to public_send
I think make sense the reduce
works with :symbol.to_proc
, and not reaching private methods.
Hanmac (Hans Mackowiak) wrote:
reduce(&:+) is different from
reduce(:+), this one has nothing to do with :+.to_procreduce/inject with symbol param does call the method internally without checking if its private or not
Updated by Hanmac (Hans Mackowiak) over 7 years ago
i think you still mix reduce(&:+) with reduce(:+)
both are two totally different ways to call this method.
(the later doesn't go the way with a Proc object)
because reduce("+") works too
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
- Status changed from Open to Closed
Applied in changeset trunk|r58871.
enum.c: respect method visibility
- enum.c (ary_inject_op): should respect method visibility, do not
optimize uncallable method. [ruby-core:81349] [Bug #13592]
Updated by usa (Usaku NAKAMURA) over 7 years ago
- Backport changed from 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN to 2.2: WONTFIX, 2.3: WONTFIX, 2.4: UNKNOWN
memo: I think this is a bug, but it may cause some compatibility problems to change the behavior in teeny release, then I decided not to backport this to ruby_2_3.