Skip to content

Commit f294bc3

Browse files
committed
Improve CoreMethod checks to ensure the number of parameters matches values in the annotation
1 parent 09840c0 commit f294bc3

File tree

2 files changed

+52
-26
lines changed

2 files changed

+52
-26
lines changed

src/processor/java/org/truffleruby/processor/CoreModuleChecks.java

+45-17
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class CoreModuleChecks {
3434
this.processor = processor;
3535
}
3636

37-
void checks(int[] lowerFixnum, CoreMethod coreMethod, TypeElement klass, boolean hasZeroArgument) {
37+
void checks(int[] lowerFixnum, CoreMethod coreMethod, TypeElement klass, boolean hasSelfArgument) {
3838
byte[] lowerArgs = null;
3939
List<ExecutableElement> specializationMethods = new ArrayList<>();
4040

@@ -54,13 +54,11 @@ void checks(int[] lowerFixnum, CoreMethod coreMethod, TypeElement klass, boolean
5454
specializationMethods.add(specializationMethod);
5555

5656
lowerArgs = checkLowerFixnumArguments(specializationMethod, lowerArgs);
57+
5758
if (coreMethod != null) {
58-
checkAmbiguousOptionalArguments(
59-
coreMethod,
60-
specializationMethod,
61-
specializationAnnotation);
59+
checkCoreMethodArguments(coreMethod, specializationMethod, specializationAnnotation,
60+
hasSelfArgument);
6261
}
63-
6462
}
6563

6664
klassIt = processor
@@ -81,8 +79,8 @@ void checks(int[] lowerFixnum, CoreMethod coreMethod, TypeElement klass, boolean
8179
// Verify against the lowerFixnum annotation
8280
for (int i = 0; i < lowerArgs.length; i++) {
8381
boolean shouldLower = lowerArgs[i] == 0b01; // int without long
84-
if (shouldLower && !contains(lowerFixnum, hasZeroArgument ? i : i + 1)) {
85-
processor.error("should use lowerFixnum for argument " + (hasZeroArgument ? i : i + 1), klass);
82+
if (shouldLower && !contains(lowerFixnum, hasSelfArgument ? i : i + 1)) {
83+
processor.error("should use lowerFixnum for argument " + (hasSelfArgument ? i : i + 1), klass);
8684
}
8785
}
8886
}
@@ -133,10 +131,11 @@ private static boolean contains(int[] array, int value) {
133131
return false;
134132
}
135133

136-
private void checkAmbiguousOptionalArguments(
134+
private void checkCoreMethodArguments(
137135
CoreMethod coreMethod,
138136
ExecutableElement specializationMethod,
139-
Specialization specializationAnnotation) {
137+
Specialization specializationAnnotation,
138+
boolean hasSelfArgument) {
140139
List<? extends VariableElement> parameters = specializationMethod.getParameters();
141140
int n = getLastParameterIndex(parameters);
142141

@@ -145,21 +144,24 @@ private void checkAmbiguousOptionalArguments(
145144
processor.error("last argument must be a RootCallTarget for alwaysInlined ", specializationMethod);
146145
return;
147146
}
148-
n--;
147+
// All other arguments are packed as Object[]
148+
return;
149149
}
150150

151-
if (coreMethod.needsBlock() && !coreMethod.alwaysInlined()) {
151+
final int parametersCount = getParametersCount(parameters);
152+
int expectedParametersCount = coreMethod.required() + coreMethod.optional();
153+
if (hasSelfArgument) {
154+
expectedParametersCount++;
155+
}
156+
157+
if (coreMethod.needsBlock()) {
152158
if (n < 0) {
153159
processor.error("invalid block method parameter position for", specializationMethod);
154160
return;
155161
}
156162
checkParameterBlock(parameters.get(n));
157163
n--; // Ignore block argument.
158-
}
159-
160-
if (coreMethod.alwaysInlined()) {
161-
// All other arguments are packed as Object[]
162-
return;
164+
expectedParametersCount++;
163165
}
164166

165167
if (coreMethod.rest()) {
@@ -173,6 +175,13 @@ private void checkAmbiguousOptionalArguments(
173175
return;
174176
}
175177
n--; // ignore final Object[] argument
178+
expectedParametersCount++;
179+
}
180+
181+
if (parametersCount != expectedParametersCount) {
182+
processor.error("expected " + expectedParametersCount + " parameters for this @CoreMethod but there are " +
183+
parametersCount, specializationMethod);
184+
return;
176185
}
177186

178187
for (int i = 0; i < coreMethod.optional(); i++, n--) {
@@ -221,6 +230,25 @@ private static int getLastParameterIndex(List<? extends VariableElement> paramet
221230
return n;
222231
}
223232

233+
private int getParametersCount(List<? extends VariableElement> parameters) {
234+
int last = getLastParameterIndex(parameters);
235+
int count = last + 1;
236+
237+
if (count > 0) {
238+
var type = parameters.get(0).asType();
239+
if (processor.isSameType(type, processor.nodeType)) {
240+
if (processor.isSameType(type, processor.virtualFrameType)) {
241+
return count - 2;
242+
} else {
243+
return count - 1;
244+
}
245+
} else if (processor.isSameType(type, processor.virtualFrameType)) {
246+
return count - 1;
247+
}
248+
}
249+
return count;
250+
}
251+
224252
private void checkParameterUnguarded(Specialization specializationAnnotation, VariableElement parameter) {
225253
String name = parameter.getSimpleName().toString();
226254

src/processor/java/org/truffleruby/processor/CoreModuleProcessor.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public class CoreModuleProcessor extends TruffleRubyProcessor {
9393
TypeMirror rubyProcType;
9494
TypeMirror rootCallTargetType;
9595
// node types
96+
TypeMirror nodeType;
9697
TypeMirror rubyNodeType;
9798
TypeMirror rubyBaseNodeType;
9899
TypeMirror primitiveNodeType;
@@ -108,6 +109,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
108109
notProvidedType = elementUtils.getTypeElement("org.truffleruby.language.NotProvided").asType();
109110
rubyProcType = elementUtils.getTypeElement("org.truffleruby.core.proc.RubyProc").asType();
110111
rootCallTargetType = elementUtils.getTypeElement("com.oracle.truffle.api.RootCallTarget").asType();
112+
nodeType = elementUtils.getTypeElement("com.oracle.truffle.api.nodes.Node").asType();
111113
rubyNodeType = elementUtils.getTypeElement("org.truffleruby.language.RubyNode").asType();
112114
rubyBaseNodeType = elementUtils.getTypeElement("org.truffleruby.language.RubyBaseNode").asType();
113115
primitiveNodeType = elementUtils.getTypeElement("org.truffleruby.builtins.PrimitiveNode").asType();
@@ -188,23 +190,19 @@ private void processCoreModule(TypeElement coreModuleElement) throws IOException
188190
if (coreMethod != null) {
189191
// Do not use needsSelf=true in module functions, it is either the module/class or the instance.
190192
// Usage of needsSelf is quite rare for singleton methods (except constructors).
191-
boolean needsSelf = coreMethod.constructor() ||
193+
boolean hasSelfArgument = coreMethod.constructor() ||
192194
(!coreMethod.isModuleFunction() && !coreMethod.onSingleton() &&
193195
coreMethod.needsSelf());
194196

195-
CoreMethod checkAmbiguous = !coreMethod.alwaysInlined() &&
196-
(coreMethod.optional() > 0 || coreMethod.needsBlock())
197-
? coreMethod
198-
: null;
199-
coreModuleChecks.checks(coreMethod.lowerFixnum(), checkAmbiguous, klass, needsSelf);
197+
coreModuleChecks.checks(coreMethod.lowerFixnum(), coreMethod, klass, hasSelfArgument);
200198
if (!inherits(e.asType(), coreMethodNodeType) &&
201199
!inherits(e.asType(), alwaysInlinedMethodNodeType)) {
202200
error(e +
203201
" should inherit from CoreMethodArrayArgumentsNode, CoreMethodNode, AlwaysInlinedMethodNode",
204202
e);
205203
}
206204
processCoreMethod(stream, rubyStream, coreModuleElement, coreModule, klass, coreMethod,
207-
needsSelf);
205+
hasSelfArgument);
208206
}
209207
}
210208
}
@@ -287,7 +285,7 @@ private void processCoreMethod(
287285
CoreModule coreModule,
288286
TypeElement klass,
289287
CoreMethod coreMethod,
290-
boolean needsSelf) {
288+
boolean hasSelfArgument) {
291289
final StringJoiner names = new StringJoiner(", ");
292290
for (String name : coreMethod.names()) {
293291
names.add(quote(name));
@@ -312,7 +310,7 @@ private void processCoreMethod(
312310

313311
int numberOfArguments = getNumberOfArguments(coreMethod);
314312
String[] argumentNamesFromAnnotation = coreMethod.argumentNames();
315-
final List<String> argumentNames = getArgumentNames(klass, argumentNamesFromAnnotation, needsSelf,
313+
final List<String> argumentNames = getArgumentNames(klass, argumentNamesFromAnnotation, hasSelfArgument,
316314
coreMethod.alwaysInlined(),
317315
numberOfArguments);
318316

0 commit comments

Comments
 (0)