8167974: MethodHandles.iteratedLoop(...) fails with CCE in the case of iterating over array
8167966: MethodHandles.iteratedLoop fails with IAE in the case of correct arguments Reviewed-by: redestad
This commit is contained in:
parent
674c5463e3
commit
1730680ce7
@ -5347,7 +5347,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
||||
* {@code (V T A...)} must have at least one {@code A} type, and the default iterator
|
||||
* handle parameter is adjusted to accept the leading {@code A} type, as if by
|
||||
* the {@link MethodHandle#asType asType} conversion method.
|
||||
* The leading {@code A} type must be {@code Iterable} or a subtype thereof, or an array type.
|
||||
* The leading {@code A} type must be {@code Iterable} or a subtype thereof.
|
||||
* This conversion step, done at loop construction time, must not throw a {@code WrongMethodTypeException}.
|
||||
* </ul>
|
||||
* <p>
|
||||
@ -5374,7 +5374,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
||||
* V iteratedLoop(A... a...) {
|
||||
* Iterator<T> it = iterator(a...);
|
||||
* V v = init(a...);
|
||||
* for (T t : it) {
|
||||
* while (it.hasNext()) {
|
||||
* T t = it.next();
|
||||
* v = body(v, t, a...);
|
||||
* }
|
||||
* return v;
|
||||
@ -5483,49 +5484,59 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
||||
Objects.requireNonNull(body);
|
||||
MethodType bodyType = body.type();
|
||||
Class<?> returnType = bodyType.returnType();
|
||||
List<Class<?>> innerList = bodyType.parameterList();
|
||||
List<Class<?>> internalParamList = bodyType.parameterList();
|
||||
// strip leading V value if present
|
||||
int vsize = (returnType == void.class ? 0 : 1);
|
||||
if (vsize != 0 && (innerList.size() == 0 || innerList.get(0) != returnType)) {
|
||||
if (vsize != 0 && (internalParamList.size() == 0 || internalParamList.get(0) != returnType)) {
|
||||
// argument list has no "V" => error
|
||||
MethodType expected = bodyType.insertParameterTypes(0, returnType);
|
||||
throw misMatchedTypes("body function", bodyType, expected);
|
||||
} else if (innerList.size() <= vsize) {
|
||||
} else if (internalParamList.size() <= vsize) {
|
||||
// missing T type => error
|
||||
MethodType expected = bodyType.insertParameterTypes(vsize, Object.class);
|
||||
throw misMatchedTypes("body function", bodyType, expected);
|
||||
}
|
||||
//Class<?> elementType = innerList.get(vsize); // do not need this
|
||||
List<Class<?>> outerList = innerList.subList(vsize + 1, innerList.size());
|
||||
if (outerList.isEmpty()) {
|
||||
// special case; take lists from iterator handle
|
||||
outerList = ((iterator != null)
|
||||
? iterator.type().parameterList()
|
||||
: Arrays.asList(Iterable.class));
|
||||
innerList = bodyType.insertParameterTypes(vsize + 1, outerList).parameterList();
|
||||
}
|
||||
List<Class<?>> externalParamList = internalParamList.subList(vsize + 1, internalParamList.size());
|
||||
Class<?> iterableType = null;
|
||||
if (iterator != null) {
|
||||
// special case; if the body handle only declares V and T then
|
||||
// the external parameter list is obtained from iterator handle
|
||||
if (externalParamList.isEmpty()) {
|
||||
externalParamList = iterator.type().parameterList();
|
||||
}
|
||||
MethodType itype = iterator.type();
|
||||
if (!Iterator.class.isAssignableFrom(itype.returnType())) {
|
||||
throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
|
||||
}
|
||||
if (!itype.effectivelyIdenticalParameters(0, outerList)) {
|
||||
MethodType expected = methodType(itype.returnType(), outerList);
|
||||
if (!itype.effectivelyIdenticalParameters(0, externalParamList)) {
|
||||
MethodType expected = methodType(itype.returnType(), externalParamList);
|
||||
throw misMatchedTypes("iterator parameters", itype, expected);
|
||||
}
|
||||
} else {
|
||||
if (externalParamList.isEmpty()) {
|
||||
// special case; if the iterator handle is null and the body handle
|
||||
// only declares V and T then the external parameter list consists
|
||||
// of Iterable
|
||||
externalParamList = Arrays.asList(Iterable.class);
|
||||
iterableType = Iterable.class;
|
||||
} else {
|
||||
// special case; if the iterator handle is null and the external
|
||||
// parameter list is not empty then the first parameter must be
|
||||
// assignable to Iterable
|
||||
iterableType = externalParamList.get(0);
|
||||
if (!Iterable.class.isAssignableFrom(iterableType)) {
|
||||
throw newIllegalArgumentException(
|
||||
"inferred first loop argument must inherit from Iterable: " + iterableType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (init != null) {
|
||||
MethodType initType = init.type();
|
||||
if (initType.returnType() != returnType ||
|
||||
!initType.effectivelyIdenticalParameters(0, outerList)) {
|
||||
throw misMatchedTypes("loop initializer", initType, methodType(returnType, outerList));
|
||||
!initType.effectivelyIdenticalParameters(0, externalParamList)) {
|
||||
throw misMatchedTypes("loop initializer", initType, methodType(returnType, externalParamList));
|
||||
}
|
||||
}
|
||||
Class<?> iterableType = outerList.isEmpty() ? null : outerList.get(0);
|
||||
if (iterableType != null && !Iterable.class.isAssignableFrom(iterableType) && !iterableType.isArray()) {
|
||||
throw newIllegalArgumentException(
|
||||
"inferred first loop argument must be an array or inherit from Iterable: " + iterableType);
|
||||
}
|
||||
return iterableType; // help the caller a bit
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
* @bug 8153637
|
||||
* @bug 8154751
|
||||
* @bug 8154754
|
||||
* @bug 8167974
|
||||
* @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
|
||||
*/
|
||||
|
||||
@ -800,7 +801,8 @@ public class LoopCombinatorTest {
|
||||
{l_it, l_i, isl_i, ""},
|
||||
{l_it, null, sl_v, ""},
|
||||
{li_it, li_i, isli_i, ""},
|
||||
{il_it, null, sil_v, "inferred first loop argument must inherit from Iterable: int"},
|
||||
{null, null, sil_v, "inferred first loop argument must inherit from Iterable: int"},
|
||||
{il_it, null, sil_v, ""},
|
||||
{li_it, null, sli_v, ""},
|
||||
{sl_v, null, sl_v, "iteratedLoop first argument must have Iterator return type"},
|
||||
{li_it, l_it, sl_v,
|
||||
|
Loading…
x
Reference in New Issue
Block a user