1 /*
2 * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
251 if (implIsInstanceMethod) {
252 final Class<?> receiverClass;
253
254 // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
255 if (capturedArity == 0) {
256 // receiver is function parameter
257 capturedStart = 0;
258 samStart = 1;
259 receiverClass = dynamicMethodType.parameterType(0);
260 } else {
261 // receiver is a captured variable
262 capturedStart = 1;
263 samStart = capturedArity;
264 receiverClass = factoryType.parameterType(0);
265 }
266
267 // check receiver type
268 if (!implClass.isAssignableFrom(receiverClass)) {
269 throw new LambdaConversionException(
270 String.format("Invalid receiver type %s; not a subtype of implementation type %s",
271 receiverClass, implClass));
272 }
273 } else {
274 // no receiver
275 capturedStart = 0;
276 samStart = capturedArity;
277 }
278
279 // Check for exact match on non-receiver captured arguments
280 for (int i=capturedStart; i<capturedArity; i++) {
281 Class<?> implParamType = implMethodType.parameterType(i);
282 Class<?> capturedParamType = factoryType.parameterType(i);
283 if (!capturedParamType.equals(implParamType)) {
284 throw new LambdaConversionException(
285 String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
286 i, capturedParamType, implParamType));
287 }
288 }
289 // Check for adaptation match on non-receiver SAM arguments
290 for (int i=samStart; i<implArity; i++) {
291 Class<?> implParamType = implMethodType.parameterType(i);
351 // both are primitive: widening
352 Wrapper wto = forPrimitiveType(toType);
353 return wto.isConvertibleFrom(wfrom);
354 } else {
355 // from primitive to reference: boxing
356 return toType.isAssignableFrom(wfrom.wrapperType());
357 }
358 } else {
359 if (toType.isPrimitive()) {
360 // from reference to primitive: unboxing
361 Wrapper wfrom;
362 if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
363 // fromType is a primitive wrapper; unbox+widen
364 Wrapper wto = forPrimitiveType(toType);
365 return wto.isConvertibleFrom(wfrom);
366 } else {
367 // must be convertible to primitive
368 return !strict;
369 }
370 } else {
371 // both are reference types: fromType should be a superclass of toType.
372 return !strict || toType.isAssignableFrom(fromType);
373 }
374 }
375 }
376
377 /**
378 * Check type adaptability for return types --
379 * special handling of void type) and parameterized fromType
380 * @return True if 'fromType' can be converted to 'toType'
381 */
382 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
383 return toType.equals(void.class)
384 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
385 }
386 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
387 if (fromType.equals(void.class) || toType.equals(void.class)) return fromType.equals(toType);
388 else return isAdaptableTo(fromType, toType, true);
389 }
390
391
|
1 /*
2 * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
251 if (implIsInstanceMethod) {
252 final Class<?> receiverClass;
253
254 // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
255 if (capturedArity == 0) {
256 // receiver is function parameter
257 capturedStart = 0;
258 samStart = 1;
259 receiverClass = dynamicMethodType.parameterType(0);
260 } else {
261 // receiver is a captured variable
262 capturedStart = 1;
263 samStart = capturedArity;
264 receiverClass = factoryType.parameterType(0);
265 }
266
267 // check receiver type
268 if (!implClass.isAssignableFrom(receiverClass)) {
269 throw new LambdaConversionException(
270 String.format("Invalid receiver type %s; not a subtype of implementation type %s",
271 receiverClass.descriptorString(), implClass.descriptorString()));
272 }
273 } else {
274 // no receiver
275 capturedStart = 0;
276 samStart = capturedArity;
277 }
278
279 // Check for exact match on non-receiver captured arguments
280 for (int i=capturedStart; i<capturedArity; i++) {
281 Class<?> implParamType = implMethodType.parameterType(i);
282 Class<?> capturedParamType = factoryType.parameterType(i);
283 if (!capturedParamType.equals(implParamType)) {
284 throw new LambdaConversionException(
285 String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
286 i, capturedParamType, implParamType));
287 }
288 }
289 // Check for adaptation match on non-receiver SAM arguments
290 for (int i=samStart; i<implArity; i++) {
291 Class<?> implParamType = implMethodType.parameterType(i);
351 // both are primitive: widening
352 Wrapper wto = forPrimitiveType(toType);
353 return wto.isConvertibleFrom(wfrom);
354 } else {
355 // from primitive to reference: boxing
356 return toType.isAssignableFrom(wfrom.wrapperType());
357 }
358 } else {
359 if (toType.isPrimitive()) {
360 // from reference to primitive: unboxing
361 Wrapper wfrom;
362 if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
363 // fromType is a primitive wrapper; unbox+widen
364 Wrapper wto = forPrimitiveType(toType);
365 return wto.isConvertibleFrom(wfrom);
366 } else {
367 // must be convertible to primitive
368 return !strict;
369 }
370 } else {
371 // fromType should be a superclass of toType
372 return !strict || toType.isAssignableFrom(fromType);
373 }
374 }
375 }
376
377 /**
378 * Check type adaptability for return types --
379 * special handling of void type) and parameterized fromType
380 * @return True if 'fromType' can be converted to 'toType'
381 */
382 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
383 return toType.equals(void.class)
384 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
385 }
386 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
387 if (fromType.equals(void.class) || toType.equals(void.class)) return fromType.equals(toType);
388 else return isAdaptableTo(fromType, toType, true);
389 }
390
391
|