diff --git a/CHANGELOG.md b/CHANGELOG.md index 978f8c95170..0388b9e7f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Bug fixes: * Fix parsing literal floats when the locale does not use `.` for the decimal separator (e.g. `LANG=fr_FR.UTF-8`) (#3512, @eregon). * Fix `IO#{read_nonblock,readpartial,sysread}`, `BasicSocket#{recv,recv_nonblock}`, `{Socket,UDPSocket}#recvfrom_nonblock`, `UnixSocket#recvfrom` and preserve a provided buffer's encoding (#3506, @andrykonchyn). * Repair `IO#{wait_readable,wait_writable,wait}` to be interruptible (#3504, @andrykonchin). +* Fix Hash value omission for constant names (@andrykonchin). Compatibility: diff --git a/spec/truffle/parsing/fixtures/hashes/with_omitted_value_and_constant.yaml b/spec/truffle/parsing/fixtures/hashes/with_omitted_value_and_constant.yaml new file mode 100644 index 00000000000..235604e331e --- /dev/null +++ b/spec/truffle/parsing/fixtures/hashes/with_omitted_value_and_constant.yaml @@ -0,0 +1,50 @@ +subject: "Hash" +description: "with omitted value and a constant" +notes: > + treats name as a constant +focused_on_node: "org.truffleruby.core.hash.library.PackedHashStoreLibrary$SmallHashLiteralNode" +ruby: | + A = 100500 + {A:, b: 42} +ast: | + PackedHashStoreLibraryFactory$SmallHashLiteralNodeGen + attributes: + flags = 1 + sourceCharIndex = 11 + sourceLength = 11 + children: + keyValues = [ + ObjectLiteralNode + attributes: + flags = 0 + object = :A + sourceCharIndex = 12 + sourceLength = 2 + ReadConstantWithLexicalScopeNode + attributes: + flags = 0 + lexicalScope = :: Object + name = "A" + sourceCharIndex = 12 + sourceLength = 2 + children: + getConstantNode = + GetConstantNodeGen + lookupConstantNode = + LookupConstantWithLexicalScopeNodeGen + attributes: + lexicalScope = :: Object + name = "A" + ObjectLiteralNode + attributes: + flags = 0 + object = :b + sourceCharIndex = 16 + sourceLength = 2 + IntegerFixnumLiteralNode + attributes: + flags = 0 + sourceCharIndex = 19 + sourceLength = 2 + value = 42 + ] \ No newline at end of file diff --git a/src/main/java/org/truffleruby/parser/YARPTranslator.java b/src/main/java/org/truffleruby/parser/YARPTranslator.java index 5c308b652b1..68dcabd6e75 100644 --- a/src/main/java/org/truffleruby/parser/YARPTranslator.java +++ b/src/main/java/org/truffleruby/parser/YARPTranslator.java @@ -1963,8 +1963,10 @@ public RubyNode visitHashNode(Nodes.HashNode node) { keyValues.add(keyNode); + // when value is omitted, e.g. `a = 1; {a: }` if (assocNode.value instanceof Nodes.ImplicitNode implicit) { if (implicit.value instanceof Nodes.CallNode call) { + // a special case for a method call because // Prism doesn't set VARIABLE_CALL flag int flags = call.flags | Nodes.CallNodeFlags.VARIABLE_CALL; final var copy = new Nodes.CallNode((short) flags, call.receiver, call.name, call.arguments, @@ -1972,11 +1974,10 @@ public RubyNode visitHashNode(Nodes.HashNode node) { final RubyNode valueNode = copy.accept(this); keyValues.add(valueNode); - } else if (implicit.value instanceof Nodes.LocalVariableReadNode localVariableRead) { - final RubyNode valueNode = localVariableRead.accept(this); - keyValues.add(valueNode); } else { - throw CompilerDirectives.shouldNotReachHere(); + // expect here Nodes.LocalVariableReadNode or Nodes.ConstantReadNode + final RubyNode valueNode = implicit.value.accept(this); + keyValues.add(valueNode); } } else { keyValues.add(assocNode.value.accept(this)); diff --git a/test/mri/excludes/TestRubyLiteral.rb b/test/mri/excludes/TestRubyLiteral.rb index 675408da0ad..4c72a663a76 100644 --- a/test/mri/excludes/TestRubyLiteral.rb +++ b/test/mri/excludes/TestRubyLiteral.rb @@ -1,2 +1 @@ exclude :test_integer, "needs investigation" -exclude :test_hash_value_omission, "NameError: undefined local variable or method `FOO' for #"