< prev index next > src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
Print this page
/*
- * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.invoke;
+ import jdk.internal.value.PrimitiveClass;
import sun.invoke.util.Wrapper;
import java.lang.reflect.Modifier;
import static java.lang.invoke.MethodHandleInfo.*;
throw new LambdaConversionException(String.format(
"%s is not an interface",
interfaceClass.getName()));
}
+ if (interfaceClass.isIdentity() || interfaceClass.isValue()) {
+ throw new LambdaConversionException(String.format(
+ "%s is %s interface",
+ interfaceClass.getName(),
+ interfaceClass.isIdentity() ? "an identity" : "a value"));
+ }
+
for (Class<?> c : altInterfaces) {
if (!c.isInterface()) {
throw new LambdaConversionException(String.format(
"%s is not an interface",
c.getName()));
samStart = capturedArity;
receiverClass = factoryType.parameterType(0);
}
// check receiver type
- if (!implClass.isAssignableFrom(receiverClass)) {
+ if (!PrimitiveClass.asPrimaryType(implClass).isAssignableFrom(PrimitiveClass.asPrimaryType(receiverClass))) {
throw new LambdaConversionException(
String.format("Invalid receiver type %s; not a subtype of implementation type %s",
- receiverClass, implClass));
+ receiverClass.descriptorString(), implClass.descriptorString()));
}
} else {
// no receiver
capturedStart = 0;
samStart = capturedArity;
/** Validate that the given descriptor's types are compatible with {@code dynamicMethodType} **/
private void checkDescriptor(MethodType descriptor) throws LambdaConversionException {
for (int i = 0; i < dynamicMethodType.parameterCount(); i++) {
Class<?> dynamicParamType = dynamicMethodType.parameterType(i);
Class<?> descriptorParamType = descriptor.parameterType(i);
- if (!descriptorParamType.isAssignableFrom(dynamicParamType)) {
+ if (!PrimitiveClass.asPrimaryType(descriptorParamType).isAssignableFrom(PrimitiveClass.asPrimaryType(dynamicParamType))) {
String msg = String.format("Type mismatch for dynamic parameter %d: %s is not a subtype of %s",
i, dynamicParamType, descriptorParamType);
throw new LambdaConversionException(msg);
}
}
} else {
// must be convertible to primitive
return !strict;
}
} else {
- // both are reference types: fromType should be a superclass of toType.
- return !strict || toType.isAssignableFrom(fromType);
+ // primitive types: fromType and toType are types of the same primitive class
+ // identity types: fromType should be a superclass of toType.
+ return !strict || canConvert(fromType, toType);
}
}
}
+ /**
+ * Tests if {@code fromType} can be converted to {@code toType}
+ * via an identity conversion, via a widening reference conversion or
+ * via primitive class narrowing and widening conversions.
+ * <p>
+ * If {@code fromType} represents a class or interface, this method
+ * returns {@code true} if {@code toType} is the same as,
+ * or is a superclass or superinterface of, {@code fromType}.
+ * <p>
+ * If {@code fromType} and {@code toType} is of the same primitive class,
+ * this method returns {@code true}.
+ * <p>
+ * Otherwise, this method returns {@code false}.
+ *
+ * @param fromType the {@code Class} object to be converted from
+ * @param toType the {@code Class} object to be converted to
+ * @return {@code true} if {@code fromType} can be converted to {@code toType}
+ */
+ private boolean canConvert(Class<?> fromType, Class<?> toType) {
+ if (toType.isAssignableFrom(fromType)) {
+ return true;
+ }
+
+ if (fromType.isValue() && toType.isValue()) {
+ // val projection can be converted to ref projection; or vice verse
+ return PrimitiveClass.asPrimaryType(fromType) == PrimitiveClass.asPrimaryType(toType);
+ }
+
+ return false;
+ }
+
/**
* Check type adaptability for return types --
* special handling of void type) and parameterized fromType
* @return True if 'fromType' can be converted to 'toType'
*/
< prev index next >