Issue #10753 has been updated by Yui NARUSE.

Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED to 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: DONE

ruby_2_2 r49409 merged revision(s) 49322.

----------------------------------------
Bug #10753: Refined class returns unexpected value when call public_method_defined?, protected_method_defined?, private_method_defined?
https://bugs.ruby-lang.org/issues/10753#change-51220

* Author: Seiei Higa
* Status: Closed
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.3.0dev (2015-01-18 trunk 49312) [x86_64-darwin14]
* Backport: 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: DONE
----------------------------------------
When I call `public_method_defined?` or `protected_method_defined?` or `private_method_defined?` methods of the class,
the result is not expected if the method is refined.

i confirmed with following example programs in ruby-trunk, 2.0.0-p598, 2.1.5, 2.2.0

examples
=======

bug_refined_method_defined.rb
-----------------------------

``` ruby
c = Class.new do
  def refined_public; end
  def refined_protected; end
  def refined_private; end

  public :refined_public
  protected :refined_protected
  private :refined_private
end

m = Module.new do
  refine(c) do
    def refined_public; end
    def refined_protected; end
    def refined_private; end

    public :refined_public
    protected :refined_protected
    private :refined_private
  end
end

using m

predicate_methods = %i(
  method_defined?
  public_method_defined?
  protected_method_defined?
  private_method_defined?
)

methods = %i(
  refined_public
  refined_protected
  refined_private
)
predicate_methods.each do |predicate_method|
  puts predicate_method
  puts '-' * 8
  methods.each do |method|
    puts "#{predicate_method}(#{method}) # => #{c.send(predicate_method, method)}"
  end
  puts
end
```

expected:
---------

``` console
$ ./ruby --disable-gems bug_refined_method_defined.rb
method_defined?
--------
method_defined?(refined_public) # => true
method_defined?(refined_protected) # => true
method_defined?(refined_private) # => false

public_method_defined?
--------
public_method_defined?(refined_public) # => true
public_method_defined?(refined_protected) # => false
public_method_defined?(refined_private) # => false

protected_method_defined?
--------
protected_method_defined?(refined_public) # => false
protected_method_defined?(refined_protected) # => true
protected_method_defined?(refined_private) # => false

private_method_defined?
--------
private_method_defined?(refined_public) # => false
private_method_defined?(refined_protected) # => false
private_method_defined?(refined_private) # => true
```

actual:
-------

``` console
$ ./ruby --disable-gems bug_refined_method_defined.rb
method_defined?
--------
method_defined?(refined_public) # => true
method_defined?(refined_protected) # => true
method_defined?(refined_private) # => false

public_method_defined?
--------
public_method_defined?(refined_public) # => true
public_method_defined?(refined_protected) # => true
public_method_defined?(refined_private) # => true

protected_method_defined?
--------
protected_method_defined?(refined_public) # => false
protected_method_defined?(refined_protected) # => false
protected_method_defined?(refined_private) # => false

private_method_defined?
--------
private_method_defined?(refined_public) # => false
private_method_defined?(refined_protected) # => false
private_method_defined?(refined_private) # => false
```

bug_undefined_refined_method_defined.rb
=======================================

``` ruby
c = Class.new
m = Module.new do
  refine(c) do
    def undefined_refined_public; end
    def undefined_refined_protected; end
    def undefined_refined_private; end
    public :undefined_refined_public
    protected :undefined_refined_protected
    private :undefined_refined_private
  end
end

using m

predicate_methods = %i(
  method_defined?
  public_method_defined?
  protected_method_defined?
  private_method_defined?
)

methods = %i(
  undefined_refined_public
  undefined_refined_protected
  undefined_refined_private
)
predicate_methods.each do |predicate_method|
  puts predicate_method
  puts '-' * 8
  methods.each do |method|
    puts "#{predicate_method}(#{method}) # => #{c.send(predicate_method, method)}"
  end
  puts
end
```

expected:
---------

``` console
$ ./ruby --disable-gems bug_undefined_refined_method_defined.rb
method_defined?
--------
method_defined?(undefined_refined_public) # => false
method_defined?(undefined_refined_protected) # => false
method_defined?(undefined_refined_private) # => false

public_method_defined?
--------
public_method_defined?(undefined_refined_public) # => false
public_method_defined?(undefined_refined_protected) # => false
public_method_defined?(undefined_refined_private) # => false

protected_method_defined?
--------
protected_method_defined?(undefined_refined_public) # => false
protected_method_defined?(undefined_refined_protected) # => false
protected_method_defined?(undefined_refined_private) # => false

private_method_defined?
--------
private_method_defined?(undefined_refined_public) # => false
private_method_defined?(undefined_refined_protected) # => false
private_method_defined?(undefined_refined_private) # => false
```

actual:
-------

``` console
$ ./ruby --disable-gems bug_undefined_refined_method_defined.rb
method_defined?
--------
method_defined?(undefined_refined_public) # => false
method_defined?(undefined_refined_protected) # => false
method_defined?(undefined_refined_private) # => false

public_method_defined?
--------
public_method_defined?(undefined_refined_public) # => true
public_method_defined?(undefined_refined_protected) # => true
public_method_defined?(undefined_refined_private) # => true

protected_method_defined?
--------
protected_method_defined?(undefined_refined_public) # => false
protected_method_defined?(undefined_refined_protected) # => false
protected_method_defined?(undefined_refined_private) # => false

private_method_defined?
--------
private_method_defined?(undefined_refined_public) # => false
private_method_defined?(undefined_refined_protected) # => false
private_method_defined?(undefined_refined_private) # => false
```

---Files--------------------------------
bug_refined_method_defined.rb (825 Bytes)
bug_undefined_refined_method_defined.rb (740 Bytes)
0001-vm_method.c-method-defined-should-not-use-refinement.patch (3.95 KB)


-- 
https://bugs.ruby-lang.org/