Skip to content

Commit d1a2518

Browse files
committed
Check that NotProvided is not used if the last argument of a Primitive Specialization is typed as a RubyProc
1 parent d9c6baf commit d1a2518

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-11
lines changed

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

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package org.truffleruby.processor;
1111

12+
import java.util.ArrayList;
1213
import java.util.List;
1314

1415
import javax.lang.model.element.Element;
@@ -34,6 +35,7 @@ static void checks(
3435
TypeElement klass,
3536
boolean hasZeroArgument) {
3637
byte[] lowerArgs = null;
38+
List<ExecutableElement> specializationMethods = new ArrayList<>();
3739

3840
TypeElement klassIt = klass;
3941
while (!processor.isNodeBaseType(klassIt)) {
@@ -48,6 +50,7 @@ static void checks(
4850
if (specializationAnnotation == null) {
4951
continue; // we are interested only in Specialization methods
5052
}
53+
specializationMethods.add(specializationMethod);
5154

5255
lowerArgs = checkLowerFixnumArguments(processor, specializationMethod, lowerArgs);
5356
if (coreMethod != null) {
@@ -66,11 +69,15 @@ static void checks(
6669
.getTypeElement(klassIt.getSuperclass().toString());
6770
}
6871

69-
if (lowerArgs == null) {
70-
processor.error("could not find specializations (lowerArgs == null)", klass);
72+
if (specializationMethods.isEmpty()) {
73+
processor.error("could not find specializations", klass);
7174
return;
7275
}
7376

77+
if (coreMethod == null) { // @Primitive
78+
checkPrimitiveArguments(processor, specializationMethods);
79+
}
80+
7481
// Verify against the lowerFixnum annotation
7582
for (int i = 0; i < lowerArgs.length; i++) {
7683
boolean shouldLower = lowerArgs[i] == 0b01; // int without long
@@ -134,15 +141,7 @@ private static void checkAmbiguousOptionalArguments(
134141
ExecutableElement specializationMethod,
135142
Specialization specializationAnnotation) {
136143
List<? extends VariableElement> parameters = specializationMethod.getParameters();
137-
int n = parameters.size() - 1;
138-
// Ignore all the @Cached methods from our consideration.
139-
while (n >= 0 &&
140-
(parameters.get(n).getAnnotation(Cached.class) != null ||
141-
parameters.get(n).getAnnotation(CachedLibrary.class) != null ||
142-
parameters.get(n).getAnnotation(CachedContext.class) != null ||
143-
parameters.get(n).getAnnotation(CachedLanguage.class) != null)) {
144-
n--;
145-
}
144+
int n = getLastParameterIndex(parameters);
146145

147146
if (coreMethod.needsBlock()) {
148147
if (n < 0) {
@@ -175,6 +174,46 @@ private static void checkAmbiguousOptionalArguments(
175174
}
176175
}
177176

177+
private static void checkPrimitiveArguments(
178+
CoreModuleProcessor processor,
179+
List<ExecutableElement> specializationMethods) {
180+
boolean hasRubyProcLastArgument = false;
181+
for (ExecutableElement specialization : specializationMethods) {
182+
List<? extends VariableElement> parameters = specialization.getParameters();
183+
int last = getLastParameterIndex(parameters);
184+
if (last >= 0 && processor.isSameType(parameters.get(last).asType(), processor.rubyProcType)) {
185+
hasRubyProcLastArgument = true;
186+
break;
187+
}
188+
}
189+
190+
if (hasRubyProcLastArgument) {
191+
for (ExecutableElement specialization : specializationMethods) {
192+
List<? extends VariableElement> parameters = specialization.getParameters();
193+
int last = getLastParameterIndex(parameters);
194+
VariableElement parameter = parameters.get(last);
195+
if (processor.isSameType(parameter.asType(), processor.notProvidedType)) {
196+
processor.error(
197+
"The last primitive parameter should not be NotProvided if it can be a RubyProc",
198+
parameter);
199+
}
200+
}
201+
}
202+
}
203+
204+
private static int getLastParameterIndex(List<? extends VariableElement> parameters) {
205+
int n = parameters.size() - 1;
206+
// Ignore all the @Cached methods from our consideration.
207+
while (n >= 0 &&
208+
(parameters.get(n).getAnnotation(Cached.class) != null ||
209+
parameters.get(n).getAnnotation(CachedLibrary.class) != null ||
210+
parameters.get(n).getAnnotation(CachedContext.class) != null ||
211+
parameters.get(n).getAnnotation(CachedLanguage.class) != null)) {
212+
n--;
213+
}
214+
return n;
215+
}
216+
178217
private static void isParameterUnguarded(
179218
CoreModuleProcessor processor,
180219
Specialization specializationAnnotation,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public class CoreModuleProcessor extends TruffleRubyProcessor {
8989
TypeMirror virtualFrameType;
9090
TypeMirror objectType;
9191
TypeMirror nilType;
92+
TypeMirror notProvidedType;
9293
TypeMirror rubyProcType;
9394
TypeMirror rubyNodeType;
9495
TypeMirror rubyBaseNodeType;
@@ -99,6 +100,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
99100
virtualFrameType = elementUtils.getTypeElement("com.oracle.truffle.api.frame.VirtualFrame").asType();
100101
objectType = elementUtils.getTypeElement("java.lang.Object").asType();
101102
nilType = elementUtils.getTypeElement("org.truffleruby.language.Nil").asType();
103+
notProvidedType = elementUtils.getTypeElement("org.truffleruby.language.NotProvided").asType();
102104
rubyProcType = elementUtils.getTypeElement("org.truffleruby.core.proc.RubyProc").asType();
103105
rubyNodeType = elementUtils.getTypeElement("org.truffleruby.language.RubyNode").asType();
104106
rubyBaseNodeType = elementUtils.getTypeElement("org.truffleruby.language.RubyBaseNode").asType();

0 commit comments

Comments
 (0)