From: "Eregon (Benoit Daloze)" Date: 2022-06-14T10:06:35+00:00 Subject: [ruby-core:108905] [Ruby master Bug#18826] Symbol#to_proc inconsistent, sometimes calls private methods Issue #18826 has been updated by Eregon (Benoit Daloze). I think Symbol#to_proc should behave like `public_send`, i.e., only allows calling public methods. That makes sense given we don't really have a call-site where we can assess the caller self easily, especially if converted to something like `lambda{|t| t.foo}` (i.e., once, in one place, on the `Symbol#to_proc` call, not on every `Proc#call` of that Proc). This is what TruffleRuby currently implements and it seems to work well and match user expectations (we've only seen one case in Rails which called a protected method, and that code has been replaced already). So for the protected example: ```ruby class Array protected def foo first end end a = [[1], [2], [3]] p a.tap(&:foo) # IMHO should be the same as a.tap { |a2| a2.foo } (which is NoMethodError) p a.collect(&:foo) # IMHO should be the same as a.collect { |o| o.foo } (which is NoMethodError) ``` Semantically, the `self` of the Proc from `Symbol#to_proc`, must be either the `self` at the time `Symbol#to_proc` is called, i.e., the main object here, or a dummy value like `nil` or maybe the Symbol itself (to signify the Proc does not actually capture the outer scope). But the `:foo.to_proc.binding.receiver` shouldn't dynamically change when calling that Proc with `Proc#call` (CRuby raises on `:foo.to_proc.binding` but let's think conceptually behind that implementation detail). The receiver should be fixed for `Symbol#to_proc` procs, just like for every other Proc instance. So I think the best and most sane (i.e., natural and does not depend on a specific implementation strategy for `Symbol#to_proc`) semantics would be to only allow calling public methods with `Symbol#to_proc`. If that's deemed too incompatible on CRuby let's at least fix the issue that `Symbol#to_proc` can call private methods sometimes. ---------------------------------------- Bug #18826: Symbol#to_proc inconsistent, sometimes calls private methods https://bugs.ruby-lang.org/issues/18826#change-97989 * Author: bjfish (Brandon Fish) * Status: Open * Priority: Normal * ruby -v: 3.0.3 * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- The following usage calls a protected method and prints "hello": ``` ruby class Test protected def referenced_columns puts "hello" end end Test.new.tap(&:referenced_columns) ``` However, the following usage results in a NoMethodError: ``` ruby class Integer private def foo 42 end end (1..4).collect(&:foo) ``` It seems to be a bug that tap calls a private method. It is also inconsistent with collect not calling private methods. -- https://bugs.ruby-lang.org/ Unsubscribe: