Project

General

Profile

Bug #14252

Refined Method Visibility Lost with Dynamic Dispatch and Reflection

Added by sonnym (Sonny Michaud) 4 months ago. Updated 4 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
[ruby-core:84539]

Description

Consider the following simple objects, one with a protected class method and another with a public class method calling on the protected method. This is accomplished using a refinement that marks the method as public on the singleton class of the original object.

class Protected
  class << self
    protected

    def print
      :protected
    end
  end
end

module Publicize
  refine Protected.singleton_class do
    public :print
  end
end

class Public
  using Publicize

  def self.print
    Protected.public_methods.include?(:print) # false
    Protected.protected_methods.include?(:print) # true

    Protected.print # works
    Protected.public_send(:print) # fails
  end
end

Public.print

This works perfectly well for the static Protected.print call, but has a number of surprises when trying to do anything more advanced. Namely:

  • Attempting to call the method with refined visibility raises a NoMethodError
  • The method appears in the protected_methods list of the original object
  • The method does not appear in the public_methods list of the original object

As a user, I would expect all those things to be not the case, since, if I opened the class directly and changed the visibility of the method, those three items would no longer be true.

History

#1 [ruby-core:84540] Updated by shugo (Shugo Maeda) 4 months ago

sonnym (Sonny Michaud) wrote:

This works perfectly well for the static Protected.print call, but has a number of surprises when trying to do anything more advanced. Namely:

  • Attempting to call the method with refined visibility raises a NoMethodError
  • The method appears in the protected_methods list of the original object
  • The method does not appear in the public_methods list of the original object

Reflection APIs do not honor refinements.
If you believe they should, please create a feature ticket for each API family.

Refinements were enabled in Kernel#send by #11476, so it may be reasonable to
enable refinements in Kernel#public_send.

#2 [ruby-core:84544] Updated by sonnym (Sonny Michaud) 4 months ago

I, personally, do not care so much about the reflection APIs, as I was just using them to confirm what I thought was happening, but I would like to at least see Kernel#public_send act similarly to Kernel#send, so I think it makes sense to scope this issue to that change.

Also available in: Atom PDF