Skip to content

Commit efd67a7

Browse files
committed
Symbol#to_proc should return -1 arity to be compatible with MRI
* Even though it does required at least one argument and so -2 would be correct in terms of how many arguments are required. * Fixes #1462.
1 parent ec90538 commit efd67a7

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Compatibility:
1515
* Change to a new system for handling Ruby objects in C extensions which
1616
greatly increases compatibility with MRI.
1717
* Implemented `BigDecimal#to_r` (#1521).
18+
* `Symbol#to_proc` now returns `-1` like on MRI (#1462).
1819

1920
# 1.0 RC 11, 15 January 2019
2021

src/main/java/org/truffleruby/core/symbol/SymbolNodes.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.oracle.truffle.api.frame.MaterializedFrame;
1919
import com.oracle.truffle.api.frame.VirtualFrame;
2020
import com.oracle.truffle.api.object.DynamicObject;
21+
import com.oracle.truffle.api.profiles.BranchProfile;
2122
import com.oracle.truffle.api.source.SourceSection;
2223
import org.truffleruby.Layouts;
2324
import org.truffleruby.builtins.CoreClass;
@@ -27,6 +28,7 @@
2728
import org.truffleruby.core.proc.ProcOperations;
2829
import org.truffleruby.core.proc.ProcType;
2930
import org.truffleruby.core.string.StringNodes;
31+
import org.truffleruby.language.RubyNode;
3032
import org.truffleruby.language.RubyRootNode;
3133
import org.truffleruby.language.SourceIndexLength;
3234
import org.truffleruby.language.Visibility;
@@ -125,7 +127,7 @@ protected DynamicObject createProc(DeclarationContext declarationContext, Intern
125127
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(
126128
sourceSection,
127129
method.getLexicalScope(),
128-
Arity.AT_LEAST_ONE,
130+
Arity.REST,
129131
null,
130132
Layouts.SYMBOL.getString(symbol),
131133
0,
@@ -138,7 +140,7 @@ protected DynamicObject createProc(DeclarationContext declarationContext, Intern
138140
// binding as this simplifies the logic elsewhere in the runtime.
139141
final MaterializedFrame declarationFrame = Truffle.getRuntime().createMaterializedFrame(args, coreLibrary().getEmptyDescriptor());
140142
final RubyRootNode rootNode = new RubyRootNode(getContext(), sourceSection, new FrameDescriptor(nil()), sharedMethodInfo,
141-
Translator.sequence(sourceIndexLength, Arrays.asList(Translator.createCheckArityNode(Arity.AT_LEAST_ONE), new SymbolProcNode(Layouts.SYMBOL.getString(symbol)))));
143+
Translator.sequence(sourceIndexLength, Arrays.asList(new CheckReceiverArgumentNode(), new SymbolProcNode(Layouts.SYMBOL.getString(symbol)))));
142144

143145
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
144146

@@ -168,6 +170,30 @@ protected DeclarationContext getDeclarationContext(VirtualFrame frame) {
168170
protected FrameDescriptor getDescriptor(VirtualFrame frame) {
169171
return frame.getFrameDescriptor();
170172
}
173+
174+
/** Not using CheckArityNode as the message is different and arity is reported as -1. */
175+
private static class CheckReceiverArgumentNode extends RubyNode {
176+
177+
private final BranchProfile noReceiverProfile = BranchProfile.create();
178+
179+
@Override
180+
public void doExecuteVoid(VirtualFrame frame) {
181+
final int given = RubyArguments.getArgumentsCount(frame);
182+
183+
if (given == 0) {
184+
noReceiverProfile.enter();
185+
throw new RaiseException(getContext(), coreExceptions().argumentError("no receiver given", this));
186+
}
187+
}
188+
189+
@Override
190+
public Object execute(VirtualFrame frame) {
191+
doExecuteVoid(frame);
192+
return nil();
193+
}
194+
195+
}
196+
171197
}
172198

173199
@CoreMethod(names = "to_s")

src/main/java/org/truffleruby/language/methods/Arity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class Arity {
2121
public static final String[] NO_KEYWORDS = new String[]{};
2222
public static final Arity NO_ARGUMENTS = new Arity(0, 0, false);
2323
public static final Arity ONE_REQUIRED = new Arity(1, 0, false);
24-
public static final Arity AT_LEAST_ONE = new Arity(1, 0, true);
24+
public static final Arity REST = new Arity(0, 0, true);
2525

2626
private final int preRequired;
2727
private final int optional;

0 commit comments

Comments
 (0)