Project

General

Profile

Actions

Bug #13592

closed

Enumerable#reduce with symbol does not respect method visibility

Added by americodls (Americo Duarte) over 7 years ago. Updated over 7 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15]
[ruby-core:81349]

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 to proc {|recv, *args| recv.__send__(self, *args)}.
So it can call private methods too.

Actions #4

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_proc

reduce/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

Actions #8

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0