Project

General

Profile

Actions

Bug #21117

closed

Inconsistent behaviour between "_1" and "it" variables

Added by radarek (Radosław Bułat) 16 days ago. Updated 9 days ago.

Status:
Closed
Assignee:
Target version:
-
ruby -v:
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
[ruby-core:120895]

Description

I believe variables _1 and it should have consistent behaviour and the same as normal local variables. Here are inconsistencies:

# 1. Assigning new value
[1, 2, 3].each { |v| v = v + 1; p v } # works as expected
[1, 2, 3].each { it = it + 1; p it } # works as expected
[1, 2, 3].each { _1 = _1 + 1; p _1 } # SyntaxError

# 2. Using operators like += on them
[1, 2, 3].each { |v| v += 1; p v } # works as expected
[1, 2, 3].each { it += 1; p it } # SyntaxError but I expected it to work correctly after 1st point
[1, 2, 3].each { _1 += 1; p _1 } # works, which is inconsistent with 1 point
# however, this one does not work
[1, 2, 3].map { _1 += 1 } # runtime error is raised: undefined method '+' for nil (NoMethodError)

If both _1 and it are advertised as block local variables then I would expect that overwriting works correctly, both using expressions like _1 = _1 + 1 and _1 *= 2.

Updated by mame (Yusuke Endoh) 16 days ago

I believe variables _1 and it should have consistent behaviour

Assignments to it are currently allowed for compatibility considerations, but I believe they may be prohibited in the future.
BTW, _1 and it are different. _1 cannot be written both inside and outside the block, but it is intentionally allowed.

and the same as normal local variables.

No, in my opinion. They are special parameters and should not be considered as just normal local variables. #20965 #21049

Updated by tompng (tomoya ishida) 14 days ago

Prism and parse.y parses these two code in the example differently.

[1, 2, 3].each { it = it + 1; p it }
[1, 2, 3].each { it += 1; p it }

I think it was designed not to break old code that uses local variable it, so maybe it should be parsed as same as the code below, just like parse.y does.

[1, 2, 3].each { it2 = it2 + 1; p it2 }
[1, 2, 3].each { it2 += 1; p it2 }

Updated by tompng (tomoya ishida) 9 days ago

  • Status changed from Open to Assigned
  • Assignee set to prism

These two should be SyntaxError, and is actually SyntaxError with --parser=parse.y

[1, 2, 3].each { _1 += 1; p _1 }
[1, 2, 3].map { _1 += 1 }

Some difference between it and _1 is by design, but the inconsistencies raised in this issue are caused by difference between parse.y and Prism and should be fixed.

Actions #4

Updated by kddnewton (Kevin Newton) 9 days ago

  • Status changed from Assigned to Closed

Applied in changeset git|127325a4bad409ee5da91084fac768934a8fd9e3.


[ruby/prism] No writing to numbered parameters

Fixes [Bug #21117]

https://github.com/ruby/prism/commit/19d4bab5a0

Actions #5

Updated by kddnewton (Kevin Newton) 9 days ago

  • Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: REQUIRED

Updated by k0kubun (Takashi Kokubun) 9 days ago

  • Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: REQUIRED to 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: DONE
Actions

Also available in: Atom PDF

Like0
Like1Like0Like0Like0Like0Like0