Skip to content

Method visibility is not preserved after redefining methods #30

@nikitakar9862

Description

@nikitakar9862

Problem

When a method is defined after a private keyword, it should remain private. However, after LowType redefines the method (using define_method), it becomes public.

This happens because the define_method sets method visibility to public by default, and the original visibility of the method is not restored.

For example:

class User
  private

  def secret
   puts "hidden"
  end
end

Expected behavior:

When a method is defined under the private keyword, if we call the method outside the class it should raise NoMethodError. This is Ruby's standard encapsulation rule.

User.new.secret # => NoMethodError (private method)

Actual behavior (after LowType processing):

But when LowType redefines the method using define_method, it makes the method public by default and does not restore the original private visibility.

User.new.secret  # => "hidden" (method became public)

Proposed Solution

  • Track where the private keyword appears in the class (using line numbers)
  • Then compare it with each method’s start_line
  • If a method is defined after the private keyword then it should be treated as private method
  • After redefining the method, explicitly restore its visibility

Example approach:

define_method(:method_name) do
  ...
end

if class_proxy.private_start_line && method_proxy.start_line >= class_proxy.private_start_line
  private :method_name
end

Additional Improvement

While working on this issue, I also found that adding file_path and start_line to param proxies and return proxies helps improve the error messages by pointing to the exact location in the source file.

@maedi brother let me know if this approach looks good. I would be happy to open a PR for it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions