Feature #22266
closedStop warning for duplicate keywords in splatted literal hashes
Description
Ruby warns for duplicate keywords in the same literal hash:
Ruby does not warn for duplicate keywords in splatted hashes:
$ ruby -we 'h = {h:}; {h:, **h}'
$ ruby -we 'h = {h:}; {**h, h:}'
$ ruby -we 'h = {h:}; {**h, h:, **h}'
$ ruby -we 'h = {h:}; {**h, **h}'
However, Ruby warns for for duplicate keywords in splatted literal hashes:
$ ruby -we '{h: 1, **{h: 1}}'
-e:1: warning: key :h is duplicated and overwritten on line 1
$ ruby -we '{**{h: 1}, h: 1}'
-e:1: warning: key :h is duplicated and overwritten on line 1
$ ruby -we '{**{h: 1}, h: 1, **{h: 1}}'
-e:1: warning: key :h is duplicated and overwritten on line 1
-e:1: warning: key :h is duplicated and overwritten on line 1
$ ruby -we '{**{h: 1}, **{h: 1}}'
-e:1: warning: key :h is duplicated and overwritten on line 1
I think Ruby should stop warning in the splatted literal hash case, for two reasons:
- Treatment of splatted literal hashes is inconsistent with treatment of splatted non-literal hashes. Even if the compiler optimizes the splatted literal hash to the same bytecode as a direct keyword, it should not emit the same warning, because fundamentally the duplicate keyword is in a different hash, not in the same hash.
- Warnings are designed to be helpful to the programmer, but unlike the warning for duplicate keywords in the same hash (a common mistake), no Ruby programmer is going to write splatted literal hashes. I can see an automated program generating splatted literal hashes, but in that case, the warnings are likely to be undesirable, just as warning for duplicate keywords in splatted non-literal hashes would be undesirable.
Consider a hypothetical future Ruby compiler that could optimize the h = {h:}; {h:, **h} to the same bytecode as {h: nil, **{h: nil}}. Would we still want to emit the same warning?
If accepted, I'm happy to work on a patch to implement this.
Updated by matz (Yukihiro Matsumoto) 11 days ago
I think the current behavior is slightly better. In {h: 1, **{h: 1}}, the overwrite is always obvious from the source, so warning about it is a consistent attitude. Whether a warning is emitted should not depend on whether the implementation merges the literal hashes.
That said, I don't have a strong opinion here. If there is a benefit other than consistency (e.g. a real-world case where this warning causes trouble), I won't reject it.
Matz.
Updated by jeremyevans0 (Jeremy Evans) 10 days ago
- Status changed from Open to Rejected
This was submitted in response to #22264, a bug report about parse.y's warnings for splatted literal hashes being different than prism's. As I mentioned, I believe no Ruby programmer would deliberately write a splatted literal hash, so the warning doesn't cause any harm other than implementation complexity. I'm not sure whether handling splatted literal hashes differently than keywords in the same hash would increase or decrease implementation complexity.
Whenever Ruby has to make a choice between consistency and programmer-friendliness, it generally chooses programmer-friendliness. If the current behavior is considered more programmer-friendly, that outweighs the consistency concerns. So I'll close this.