Skip to content

Commit c062749

Browse files
andrykonchineregon
authored andcommitted
[GR-45621] Fix {Method,Proc}#parameters method
PullRequest: truffleruby/4161
2 parents 6ab9956 + c98a236 commit c062749

File tree

14 files changed

+87
-34
lines changed

14 files changed

+87
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Compatibility:
5454
* Limit maximum encoding set size by 256 (#3039, @thomasmarshall, @goyox86).
5555
* Remove deprecated methods `Dir.exists?`, `File.exists?`, and `Kernel#=~` (#3039, @patricklinpl, @nirvdrum).
5656
* Remove deprecated `FileTest.exists?` method (#3039, @andrykonchin).
57+
* Fix {Method,Proc}#parameters and return `*`, `**` and `&` names for anonymous parameters (@andrykonchin).
5758

5859
Performance:
5960

spec/ruby/core/method/parameters_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def one_splat_one_block(*args, &block)
2222
local_is_not_parameter = {}
2323
end
2424

25+
def forward_parameters(...) end
26+
2527
def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end
2628

2729
define_method(:one_optional_defined_method) {|x = 1|}
@@ -267,6 +269,20 @@ def object.foo(&)
267269
end
268270
end
269271

272+
ruby_version_is ""..."3.1" do
273+
it "returns [:rest, :*], [:block, :&] for forward parameters operator" do
274+
m = MethodSpecs::Methods.new
275+
m.method(:forward_parameters).parameters.should == [[:rest, :*], [:block, :&]]
276+
end
277+
end
278+
279+
ruby_version_is "3.1" do
280+
it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do
281+
m = MethodSpecs::Methods.new
282+
m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]]
283+
end
284+
end
285+
270286
it "returns the args and block for a splat and block argument" do
271287
m = MethodSpecs::Methods.new
272288
m.method(:one_splat_one_block).parameters.should == [[:rest, :args], [:block, :block]]

spec/ruby/core/proc/parameters_spec.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,8 @@
170170
[:block, :_]
171171
]
172172
end
173+
174+
it "returns :nokey for **nil parameter" do
175+
proc { |**nil| }.parameters.should == [[:nokey]]
176+
end
173177
end

spec/tags/core/method/parameters_tags.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

spec/tags/core/proc/parameters_tags.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

spec/tags/library/socket/tcpsocket/initialize_tags.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ fails:TCPSocket#initialize using IPv6 when a server is listening on the given ad
55
fails:TCPSocket#initialize using IPv6 when a server is listening on the given address creates a socket which is set to close on exec
66
slow:TCPSocket#initialize raises IO::TimeoutError with :connect_timeout when no server is listening on the given address
77
slow:TCPSocket#initialize with a running server connects to a server when passed connect_timeout argument
8+
fails(transient):TCPSocket#initialize raises IO::TimeoutError with :connect_timeout when no server is listening on the given address

src/main/java/org/truffleruby/core/proc/RubyProc.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ public int getArityNumber() {
123123
}
124124

125125
public ArgumentDescriptor[] getArgumentDescriptors() {
126-
return argumentDescriptors == null ? arity.toAnonymousArgumentDescriptors() : argumentDescriptors;
126+
// parameters can be unnamed in a Proc created using Symbol#to_proc
127+
return argumentDescriptors == null ? arity.toUnnamedArgumentDescriptors() : argumentDescriptors;
127128
}
128129

129130
// region SourceLocation

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public static RootCallTarget createCallTarget(RubyLanguage language, RubySymbol
226226
0,
227227
"&:" + symbol.getString(),
228228
"Symbol#to_proc",
229-
ArgumentDescriptor.AT_LEAST_ONE);
229+
ArgumentDescriptor.AT_LEAST_ONE_UNNAMED);
230230

231231
// ModuleNodes.DefineMethodNode relies on the lambda CallTarget to always use a RubyLambdaRootNode,
232232
// and we want to use a single CallTarget for both proc and lambda.

src/main/java/org/truffleruby/language/arguments/ArgumentDescriptorUtils.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@
1515
import org.truffleruby.RubyLanguage;
1616
import org.truffleruby.core.array.ArrayHelpers;
1717
import org.truffleruby.core.array.RubyArray;
18+
import org.truffleruby.core.symbol.RubySymbol;
1819
import org.truffleruby.parser.ArgumentDescriptor;
1920
import org.truffleruby.parser.ArgumentType;
2021

2122
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
22-
import org.truffleruby.parser.TranslatorEnvironment;
23+
24+
import static org.truffleruby.parser.TranslatorEnvironment.FORWARDED_BLOCK_NAME;
25+
import static org.truffleruby.parser.TranslatorEnvironment.FORWARDED_KEYWORD_REST_NAME;
26+
import static org.truffleruby.parser.TranslatorEnvironment.FORWARDED_REST_NAME;
2327

2428
public final class ArgumentDescriptorUtils {
2529

@@ -44,16 +48,22 @@ private static RubyArray toArray(RubyLanguage language, RubyContext context, Arg
4448

4549
private static RubyArray toArray(RubyLanguage language, RubyContext context, ArgumentType argType, String name) {
4650
final Object[] store;
51+
final RubySymbol typeSymbol = language.getSymbol(argType.symbolicName);
4752

48-
if (argType.anonymous || name == null) {
49-
store = new Object[]{ language.getSymbol(argType.symbolicName) };
53+
if (argType == ArgumentType.anonrest) {
54+
store = new Object[]{ typeSymbol, language.coreSymbols.MULTIPLY };
55+
} else if (argType == ArgumentType.anonkeyrest) {
56+
store = new Object[]{ typeSymbol, language.coreSymbols.POW };
57+
} else if (argType == ArgumentType.rest && name.equals(FORWARDED_REST_NAME)) {
58+
store = new Object[]{ typeSymbol, language.coreSymbols.MULTIPLY };
59+
} else if (argType == ArgumentType.keyrest && name.equals(FORWARDED_KEYWORD_REST_NAME)) {
60+
store = new Object[]{ typeSymbol, language.coreSymbols.POW };
61+
} else if (argType == ArgumentType.block && name.equals(FORWARDED_BLOCK_NAME)) {
62+
store = new Object[]{ typeSymbol, language.coreSymbols.AMPERSAND };
63+
} else if (argType.anonymous || name == null) {
64+
store = new Object[]{ typeSymbol };
5065
} else {
51-
// make sure to normalize parameter names to "_" if they start with "_$"
52-
if (name.startsWith(TranslatorEnvironment.UNDERSCORE_PREFIX)) {
53-
name = "_";
54-
}
55-
56-
store = new Object[]{ language.getSymbol(argType.symbolicName), language.getSymbol(name) };
66+
store = new Object[]{ typeSymbol, language.getSymbol(name) };
5767
}
5868

5969
return ArrayHelpers.createArray(context, language, store);

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,31 +164,33 @@ public String[] getRequiredKeywordArguments() {
164164
return requiredKeywords;
165165
}
166166

167-
public ArgumentDescriptor[] toAnonymousArgumentDescriptors() {
167+
/** Generate argument descriptors for a method/proc that doesn't provide parameter names, e.g a core method
168+
* implemented in Java. */
169+
public ArgumentDescriptor[] toUnnamedArgumentDescriptors() {
168170
List<ArgumentDescriptor> descs = new ArrayList<>();
169171

170172
for (int i = 0; i < preRequired; i++) {
171-
descs.add(new ArgumentDescriptor(ArgumentType.anonreq));
173+
descs.add(new ArgumentDescriptor(ArgumentType.unnamedreq));
172174
}
173175

174176
for (int i = 0; i < optional; i++) {
175-
descs.add(new ArgumentDescriptor(ArgumentType.anonopt));
177+
descs.add(new ArgumentDescriptor(ArgumentType.unnamedopt));
176178
}
177179

178180
if (hasRest) {
179-
descs.add(new ArgumentDescriptor(ArgumentType.anonrest));
181+
descs.add(new ArgumentDescriptor(ArgumentType.unnamedrest));
180182
}
181183

182184
for (int i = 0; i < postRequired; i++) {
183-
descs.add(new ArgumentDescriptor(ArgumentType.anonreq));
185+
descs.add(new ArgumentDescriptor(ArgumentType.unnamedreq));
184186
}
185187

186188
for (String keyword : keywordArguments) {
187189
descs.add(new ArgumentDescriptor(ArgumentType.key, keyword));
188190
}
189191

190192
if (hasKeywordsRest) {
191-
descs.add(new ArgumentDescriptor(ArgumentType.anonkeyrest));
193+
descs.add(new ArgumentDescriptor(ArgumentType.unnamedkeyrest));
192194
}
193195

194196
return descs.toArray(ArgumentDescriptor.EMPTY_ARRAY);

0 commit comments

Comments
 (0)