Project

General

Profile

Bug #13249

Access modifiers don't have an effect inside class methods in Ruby >= 2.3

Added by abotalov (Andrei Botalov) over 2 years ago. Updated about 2 years ago.

Status:
Assigned
Priority:
Normal
Target version:
-
ruby -v:
2.3.0, 2.4.0
[ruby-core:79751]

Description

Simple example:

class C
  def self.foo
    private
    def bar
    end
  end
end
C.foo
C.new.bar

This code runs fine on Ruby 2.3 and Ruby 2.4. It raises NoMethodError on Ruby 2.2 and prior versions.
I would expect an error to be raised.

Here is some code that actually uses private access modifier inside a class method - https://github.com/evolve75/RubyTree/blob/db48c35b0a3b96e4da473b095cc00e454d8a9996/lib/tree/utils/camel_case_method_handler.rb#L60

By the way, this code raises an error as expected on Ruby 2.3 and Ruby 2.4:

class C
  def self.foo
    private def bar
    end
  end
end
C.foo
C.new.bar # NoMethodError: private method `bar' called

Related issues

Related to Ruby trunk - Bug #11571: シングルトンメソッドの中で def を使用した時の可視性が変わっているClosedActions
Related to Ruby trunk - Bug #11754: Visibility scope is kept after lexical scope is closedClosedActions

History

Updated by abotalov (Andrei Botalov) over 2 years ago

  • Description updated (diff)

Updated by abotalov (Andrei Botalov) over 2 years ago

  • Description updated (diff)
#3

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Related to Bug #11571: シングルトンメソッドの中で def を使用した時の可視性が変わっている added
#4

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Related to Bug #11754: Visibility scope is kept after lexical scope is closed added

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

Hmmm, a class singleton method should have its own visibility per invocations?

Updated by abotalov (Andrei Botalov) over 2 years ago

Well, ability to declare private methods inside class methods seems strange given that it's not possible to declare private methods inside instance methods:

class C
  def foo
    private def bar
    end
  end
end
C.new.foo # NoMethodError is raised

So I'm not sure which route would be better.

Updated by shevegen (Robert A. Heiler) over 2 years ago

The examples confuse me a bit.

Does private actually make sense on any class-method / singleton method?

I understand it as a limitation for methods on the class, where outside
calls are not allowed, only internal ones (though ruby allows one to
bypass these anyway via .send).

I am also confused by the second example:

class C
  def self.foo
    private def bar
    end
  end
end
C.foo
C.new.bar

Is that not equivalent to

private
def self.bar

?

So why would this work on the C.new.bar() level?

It is however had interesting that this worked on 2.2 and below but
was changed past that point.

Updated by abotalov (Andrei Botalov) over 2 years ago

  • Description updated (diff)

Updated by shyouhei (Shyouhei Urabe) about 2 years ago

  • Assignee set to ko1 (Koichi Sasada)
  • Status changed from Open to Assigned

We looked at this issue in yesterday's developer meeting.

The use of private in evolve75/RubyTree shown in the description is in fact wrong (methods are defined in a wrong place). That example made us think that the use of private in a method is a code smell.

We would forbid such usage in a future. For the time being, let us show warning message.

Updated by ko1 (Koichi Sasada) about 2 years ago

I will insert warning.
I will not change the current behavior.

Also available in: Atom PDF