https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112021-12-08T03:25:46ZRuby Issue Tracking SystemRuby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=952072021-12-08T03:25:46Zkoic (Koichi ITO)koic.ito@gmail.com
<ul><li><strong>Subject</strong> changed from <i>An unexpected "hash value omission" syntax error when parentheses call expr follows</i> to <i>An unexpected "hash value omission" syntax error when without parentheses call expr follows</i></li></ul> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=952082021-12-08T04:09:22Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>It is by design.</p>
<pre><code>foo key:
bar
</code></pre>
<p>was parsed as <code>foo(key: bar)</code> in Ruby 3.0 or before. It is incompatible to change it to <code>foo(key: key); bar</code>.</p>
<p>Except some traditional exceptions like <code>puts "foo"</code> and <code>require "foo"</code>, it would be good to write parentheses when a method call has any argument.</p> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=952102021-12-08T06:39:48Zkoic (Koichi ITO)koic.ito@gmail.com
<ul></ul><p>I get it. Thank you for the explanation!</p> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=953012021-12-13T02:56:57Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Status</strong> changed from <i>Rejected</i> to <i>Open</i></li></ul><p>Although it's incompatible, I think it's worth improving. I estimate that the compatibility issue is minimal.<br>
After 3.1 release, we experiment to measure how big the issue is.</p>
<p>Matz.</p> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=953052021-12-13T09:11:32Zzverok (Victor Shepelev)zverok.offline@gmail.com
<ul></ul><p>The current state of things is indeed quite confusing (Wrote a small blog post on it: <a href="https://zverok.github.io/blog/2021-12-08-value-omission-debug.html" class="external">https://zverok.github.io/blog/2021-12-08-value-omission-debug.html</a>).</p>
<p>As far as I can understand, the kind of old code that would be affected should look like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">method_call</span> <span class="ss">foo:
</span><span class="n">bar</span>
</code></pre>
<p>While using parenthesis in non-DSL method calls is the most common style currently, it is not the only one.<br>
For example, Seattle.rb's style (minitest) have optional parenthesis</p>
<p>Also, I suspect there could be a frequently/sometimes used style at least when using Rails DSL:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">validate</span> <span class="ss">:something</span><span class="p">,</span> <span class="ss">if: </span><span class="o">-></span> <span class="p">{</span><span class="n">condition</span> <span class="p">}</span>
<span class="c1"># ...when `condition` grows longer, I suspect _some_ codebases might do this:</span>
<span class="n">validate</span> <span class="ss">:something</span><span class="p">,</span> <span class="ss">if:
</span><span class="o">-></span> <span class="p">{</span><span class="n">condition</span> <span class="p">}</span>
</code></pre>
<p>Another parenthesis-less DSLs are assertions (of the same minitest and other "testunit"-alike frameworks).</p>
<p>The worst thing here, I can't think of a way of catching this incompatibility automatically, just after updating on 3.2 <em>some</em> code might break, and in a quite subtle way (for example, DSL methods receiving something <em>accidentally available</em> in current scope), or in a baffling one like <code> undefined local variable or method 'if'</code> — ugh what.</p>
<p>As an alternative, I was thinking maybe prohibit methods with keyword argument omission <strong>and</strong> parenthesis omission? E.g. make this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">p</span> <span class="ss">x: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">y: </span><span class="mi">1</span> <span class="c1"># valid</span>
<span class="nb">p</span> <span class="n">x</span><span class="p">:,</span> <span class="ss">y: </span><span class="mi">1</span> <span class="c1"># valid</span>
<span class="nb">p</span> <span class="ss">x: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">y: </span><span class="c1"># invalid, ambiguity!</span>
<span class="nb">p</span><span class="p">(</span><span class="ss">x: </span><span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">:)</span> <span class="c1"># valid</span>
</code></pre> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=953102021-12-13T16:02:22Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>I think this patch will change the meaning of <code>p x:</code> as matz said.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/parse.y b/parse.y
index 0ff3ddbb4e..d92decfc1c 100644
</span><span class="gd">--- a/parse.y
</span><span class="gi">+++ b/parse.y
</span><span class="p">@@ -9290,7 +9290,7 @@</span> parser_yylex(struct parser_params *p)
p->token_seen = token_seen;
c = (IS_lex_state(EXPR_BEG|EXPR_CLASS|EXPR_FNAME|EXPR_DOT) &&
!IS_lex_state(EXPR_LABELED));
<span class="gd">- if (c || IS_lex_state_all(EXPR_ARG|EXPR_LABELED)) {
</span><span class="gi">+ if (c || (IS_lex_state_all(EXPR_ARG|EXPR_LABELED) && p->lex.paren_nest)) {
</span> if (!fallthru) {
dispatch_scan_event(p, tIGNORED_NL);
}
</code></pre>
<p>Example:</p>
<pre><code>x = 1
p x:
2
#=> {:x=>2} # before the patch
#=> {:x=>1} # after the patch
</code></pre>
<p>If the expression is within parentheses, the behavior is be changed.</p>
<pre><code>x = 1
p(x:
2
)
#=> {:x=>2} # not changed
</code></pre>
<p>Before introducing this change, we definitely need to prepare migration path. The following patch will keep the current behavior and print a warning against code that will be changed. This can be used to estimate the impact of the compatibility.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/parse.y b/parse.y
index 0ff3ddbb4e..73deae8627 100644
</span><span class="gd">--- a/parse.y
</span><span class="gi">+++ b/parse.y
</span><span class="p">@@ -9291,6 +9291,9 @@</span> parser_yylex(struct parser_params *p)
c = (IS_lex_state(EXPR_BEG|EXPR_CLASS|EXPR_FNAME|EXPR_DOT) &&
!IS_lex_state(EXPR_LABELED));
if (c || IS_lex_state_all(EXPR_ARG|EXPR_LABELED)) {
<span class="gi">+ if (IS_lex_state_all(EXPR_ARG|EXPR_LABELED) && !p->lex.paren_nest) {
+ rb_warn0("keyword label followed by newline without parentheses will be changed in Ruby 3.3");
+ }
</span> if (!fallthru) {
dispatch_scan_event(p, tIGNORED_NL);
}
</code></pre> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=953342021-12-14T16:08:37ZDan0042 (Daniel DeLorme)
<ul></ul><p>matz (Yukihiro Matsumoto) wrote in <a href="#note-4">#note-4</a>:</p>
<blockquote>
<p>Although it's incompatible, I think it's worth improving. I estimate that the compatibility issue is minimal.<br>
After 3.1 release, we experiment to measure how big the issue is.</p>
</blockquote>
<p>Please, no.<br>
To my eye, <code>foo key:</code> looks like it continues on the next line. Changing that is both incompatible and, more importantly to me, unreadable. hash value omission is a great feature but in order to be readable imho it really requires open and close tokens. So <code>{a:, b:}</code> and <code>p(a:, b:)</code> are both readable but <code>p a:, b:</code> is not. -- 2¢</p> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=954712021-12-22T08:07:28Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>I have just noticed that Ruby 3.1's right-assignment pattern can end with <code>x:</code>.</p>
<pre><code># Works as expected on Ruby 3.1
hsh = { x: 42 }
hsh => x:
p x #=> 42
</code></pre> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=960342022-01-18T10:09:58Ztycooon (Yuri Smirnov)tycoooon@gmail.com
<ul></ul><p>Personally I would suggest only allowing shorthand syntax in case when brackets are present. So that</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">x</span> <span class="o">=</span> <span class="mi">15</span>
<span class="nb">p</span> <span class="ss">x: </span><span class="c1"># Syntax error</span>
<span class="nb">p</span><span class="p">(</span><span class="n">x</span><span class="p">:)</span> <span class="c1"># Works</span>
</code></pre>
<p>OR maybe change current behavior and require trailing backslash in order to make it use the expression on the next line:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="nb">p</span> <span class="n">a</span><span class="p">:,</span> <span class="ss">b: </span><span class="c1"># Always works like p(a:, b:)</span>
<span class="nb">p</span> <span class="n">a</span><span class="p">:,</span> <span class="ss">b: </span><span class="p">\</span>
<span class="mi">15</span>
<span class="c1"># => { a: 1, b: 15 }</span>
</code></pre> Ruby master - Bug #18396: An unexpected "hash value omission" syntax error when without parentheses call expr followshttps://bugs.ruby-lang.org/issues/18396?journal_id=970762022-03-29T21:58:09Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>mame (Yusuke Endoh) wrote in <a href="#note-6">#note-6</a>:</p>
<blockquote>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/parse.y b/parse.y
index 0ff3ddbb4e..73deae8627 100644
</span><span class="gd">--- a/parse.y
</span><span class="gi">+++ b/parse.y
</span><span class="p">@@ -9291,6 +9291,9 @@</span> parser_yylex(struct parser_params *p)
c = (IS_lex_state(EXPR_BEG|EXPR_CLASS|EXPR_FNAME|EXPR_DOT) &&
!IS_lex_state(EXPR_LABELED));
if (c || IS_lex_state_all(EXPR_ARG|EXPR_LABELED)) {
<span class="gi">+ if (IS_lex_state_all(EXPR_ARG|EXPR_LABELED) && !p->lex.paren_nest) {
+ rb_warn0("keyword label followed by newline without parentheses will be changed in Ruby 3.3");
+ }
</span> if (!fallthru) {
dispatch_scan_event(p, tIGNORED_NL);
}
</code></pre>
</blockquote>
<p>I did some testing with this and found it that warns for method definitions with required keywords, such as:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nc">obj</span><span class="o">.</span><span class="nf">foo</span> <span class="ss">a:
</span><span class="n">a</span>
<span class="k">end</span>
</code></pre>
<p>Since the behavior for that wouldn't change, I don't think this warning will work. We'll have to figure out a way to issue the warning only in the method call case and not in the method definition case. I guess that means we'll have to move the warning from the lexer to the parser.</p>