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) 27 days ago. Updated 26 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) 27 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) 27 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) 26 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