Project

General

Profile

Actions

Bug #16520

closed

Brackets ignored over multi-line

Added by abrom (Andrew Bromwich) about 4 years ago. Updated about 4 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
[ruby-core:96960]

Description

I was refactoring some code in a gem and noticed some test failures. It appears to be a bug in the tests masked by what I believe is a bug in the Ruby parser/interpreter. I've been able to boil the issue down to the following simple example:

# with variable assignment (expected result => 3)
a = (1
+2)
=> 2

# variable is assigned to the value from the second line (expected result also => 3)
a
=> 2

# without variable assignment (expected result => 3)
(1
+2)
=> 2

# with a trailing operator (works as expected, result => 3)
(1+
2)
=> 3

The Ruby interpreter seems to be ignoring the variable on the first line when an operation is split across multiple lines and the operator is on the following line despite the brackets suggesting that the operation is incomplete.

In a similar (possibly unrelated) vein, the following also results in an unexpected behaviour:

[1
+2]

Resulting in the following error raised:

SyntaxError ((irb):2: syntax error, unexpected unary+, expecting ']')

Expected result would have been

=> [3]

Note: I've also tried this on versions as far back as 1.9.3 with the same result.

Updated by mame (Yusuke Endoh) about 4 years ago

  • Status changed from Open to Rejected
(1
+2)

is equivalent to

begin
  1
  +2
end

which evaluates, discards the first line (1), and then evaluates and returns the second line (+2).

You can see a warning "unused literal ignored" on a verbose mode.

$ ruby -w -e 'a = (1
+2)'
-e:1: warning: unused literal ignored

Updated by abrom (Andrew Bromwich) about 4 years ago

Note when running the above code through the parser it's pretty clear why it's breaking, and to be honest i'm not sure if there would be a way to 'fix' it either.. hmmm

require 'parser/current'
=> true
code = <<-RUBY
(1
+2)
RUBY
=> "(1\n+ 2)\n"
ast = Parser::CurrentRuby.parse(code)
=> s(:begin,
  s(:int, 1),
  s(:int, 2))
eval code
=> 2
code_2 = <<-RUBY
(1+
2)
RUBY
=> "(1+\n2)\n"
> Parser::CurrentRuby.parse(code_2)
=> s(:begin,
  s(:send,
    s(:int, 1), :+,
    s(:int, 2)))

Updated by abrom (Andrew Bromwich) about 4 years ago

mame (Yusuke Endoh) wrote:

(1
+2)

is equivalent to

begin
  1
  +2
end

which evaluates, discards the first line (1), and then evaluates and returns the second line (+2).

You can see a warning "unused literal ignored" on a verbose mode.

$ ruby -w -e 'a = (1
+2)'
-e:1: warning: unused literal ignored

Ok, thanks @mame (Yusuke Endoh)

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0