Project

General

Profile

Actions

Bug #21661

open

Endless method definition as a default value of block parameter is wrongly accepted in Prism

Bug #21661: Endless method definition as a default value of block parameter is wrongly accepted in Prism

Added by tompng (tomoya ishida) 3 days ago. Updated about 18 hours ago.

Status:
Open
Assignee:
Target version:
-
ruby -v:
ruby 3.5.0dev (2025-11-01T00:18:01Z master 17a7b4e031) +PRISM [x86_64-linux]
[ruby-core:123632]

Description

These are syntax error in parse.y but not in Prism.

p do |a = def f = 1; b| end
p do |a = def f = 1| 2; b|c end # `|` inside block parameter

Normal assignment as a default value p do |a = b = 1| end is already syntax error.

Updated by Earlopain (Earlopain _) 2 days ago Actions #1 [ruby-core:123646]

It isn't specifically about block locals, p do |a = def f = 1, b| end is the same.

p do |a = def f = 1| 2; b|c end becomes p do |a = (def f = 1| 2); b|c end, so one block local b and method body of c. The same issue as the first example I believe.

That said, it looks inconsistent in parse.y: def foo(a = def f = 1, b); end and ->(a = def f = 1; b) {} is accepted. Why is it ok in method and lamba parameters but not in block parameters? I feel like it should be rejected in all these cases.

Updated by tompng (tomoya ishida) 1 day ago Actions #2 [ruby-core:123648]

Inside | | style block parameter, binary operators (example: 1+2, 1|2) are rejected because we need to reject ambiguous |.
On the right hand side of assignment and endless def, binary operators are allowed, unless we introduce a special state or something.
So def foo(a = b = 1+2); end, def foo(a = def f = 1+2); end, ->(a = b = 1+2){}, ->(a = def f = 1+2) {} are all consistently accepted, and consistently rejected when surrounded by {| |}.

Assignment in default value of method definition is already used. https://github.com/ruby/ruby/blob/11583f53b172ead33355330c1445964d5af47f46/array.rb#L129C3-L129C35

class Array
  def first n = unspecified = true
end

Also need to fix default value of keyword parameter proc { |a: def f = 1, **| }

Updated by Earlopain (Earlopain _) about 18 hours ago Actions #3 [ruby-core:123663]

I appreciate the explanation. I openend https://github.com/ruby/prism/pull/3702, it would be nice if you can check that the added tests match your expectation. Basically it is no endless method definition only between |...|, which is my understanding.

Actions

Also available in: PDF Atom