Project

General

Profile

Actions

Bug #21563

closed

Misleading error message when `to_proc` does not return a Proc in an Object used as a &block argument

Added by soulcutter (Bradley Schaefer) 3 days ago. Updated 3 days ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
[ruby-core:123180]

Description

When a class implements #to_proc it should always return a Proc. Nonetheless bugs are possible, and when an implementation returns something else, and is used as a block argument to a method, you get an error that claims that the argument type is the implementing class rather than the type that was returned from to_proc.

Reproduction

 class SayHi
   def call = "hi"
   def to_proc = "obviously not a proc"
 end

 def callablock(&block) = block.call
 
 callablock &SayHi.new # wrong argument type SayHi (expected Proc) (TypeError)

In real-world code it may not be this obvious that to_proc is returning the wrong type, and so I would expect the error would report the type of object returned by to_proc so that you have a more-direct path to understanding the misbehavior. In this case I would expect:

wrong argument type String (expected Proc)

Or maybe something more-descriptive as an error message, but I don't have a concrete suggestion for that.

Updated by jeremyevans0 (Jeremy Evans) 3 days ago

If we want to change the behavior in this case, we should report both the actual argument and the return value of to_proc. That's what we do for *a where a.to_a returns non-Array and for **h where h.to_hash returns non-Hash):

A = Class.new
a = A.new
def a.to_a = 1
def a.to_hash = 1
p(*a)  # can't convert A to Array (A#to_a gives Integer) (TypeError)
p(**a) # can't convert A to Hash (A#to_hash gives Integer) (TypeError)

def a.to_proc = 1
p(&a)
# currently: wrong argument type A (expected Proc) (TypeError)
# preferable: can't convert A to Proc (A#to_proc gives Integer) (TypeError)

Updated by jeremyevans0 (Jeremy Evans) 3 days ago

I submitted a PR to make the error messages for & consistent with */**: https://github.com/ruby/ruby/pull/14463

Actions #3

Updated by jeremyevans (Jeremy Evans) 3 days ago

  • Status changed from Open to Closed

Applied in changeset git|953e1ef99283d8563ff655ee6b8fcd681af79c1c.


Make invalid & operator type error message consistent with /*

If #to_proc is defined, this uses the following error message format,
matching the error message format used for * when to_a returns non-Array
and for ** when to_hash returns non-Hash:

can't convert ClassName to Proc (ClassName#to_proc gives OtherClassName)

If #to_proc is not defined, this uses the following error message format,
matching the error message format used when ** is called on a non-Hash
not implementing to_hash.

no implicit conversion of ClassName into Proc

There isn't a similar error for * when called on a non-Array not
implementing to_a, as Ruby does not raise for that case.

Fixes [Bug #21563]

Actions

Also available in: Atom PDF

Like0
Like2Like0Like0