1 /*
2 * Copyright (c) 2012, 2021, 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
254 if (implIsInstanceMethod) {
255 final Class<?> receiverClass;
256
257 // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
258 if (capturedArity == 0) {
259 // receiver is function parameter
260 capturedStart = 0;
261 samStart = 1;
262 receiverClass = dynamicMethodType.parameterType(0);
263 } else {
264 // receiver is a captured variable
265 capturedStart = 1;
266 samStart = capturedArity;
267 receiverClass = factoryType.parameterType(0);
268 }
269
270 // check receiver type
271 if (!implClass.isAssignableFrom(receiverClass)) {
272 throw new LambdaConversionException(
273 String.format("Invalid receiver type %s; not a subtype of implementation type %s",
274 receiverClass, implClass));
275 }
276 } else {
277 // no receiver
278 capturedStart = 0;
279 samStart = capturedArity;
280 }
281
282 // Check for exact match on non-receiver captured arguments
283 for (int i=capturedStart; i<capturedArity; i++) {
284 Class<?> implParamType = implMethodType.parameterType(i);
285 Class<?> capturedParamType = factoryType.parameterType(i);
286 if (!capturedParamType.equals(implParamType)) {
287 throw new LambdaConversionException(
288 String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
289 i, capturedParamType, implParamType));
290 }
291 }
292 // Check for adaptation match on non-receiver SAM arguments
293 for (int i=samStart; i<implArity; i++) {
294 Class<?> implParamType = implMethodType.parameterType(i);
354 // both are primitive: widening
355 Wrapper wto = forPrimitiveType(toType);
356 return wto.isConvertibleFrom(wfrom);
357 } else {
358 // from primitive to reference: boxing
359 return toType.isAssignableFrom(wfrom.wrapperType());
360 }
361 } else {
362 if (toType.isPrimitive()) {
363 // from reference to primitive: unboxing
364 Wrapper wfrom;
365 if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
366 // fromType is a primitive wrapper; unbox+widen
367 Wrapper wto = forPrimitiveType(toType);
368 return wto.isConvertibleFrom(wfrom);
369 } else {
370 // must be convertible to primitive
371 return !strict;
372 }
373 } else {
374 // both are reference types: fromType should be a superclass of toType.
375 return !strict || toType.isAssignableFrom(fromType);
376 }
377 }
378 }
379
380 /**
381 * Check type adaptability for return types --
382 * special handling of void type) and parameterized fromType
383 * @return True if 'fromType' can be converted to 'toType'
384 */
385 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
386 return toType.equals(void.class)
387 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
388 }
389 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
390 if (fromType.equals(void.class) || toType.equals(void.class)) return fromType.equals(toType);
391 else return isAdaptableTo(fromType, toType, true);
392 }
393
394
|
1 /*
2 * Copyright (c) 2012, 2022, 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
254 if (implIsInstanceMethod) {
255 final Class<?> receiverClass;
256
257 // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
258 if (capturedArity == 0) {
259 // receiver is function parameter
260 capturedStart = 0;
261 samStart = 1;
262 receiverClass = dynamicMethodType.parameterType(0);
263 } else {
264 // receiver is a captured variable
265 capturedStart = 1;
266 samStart = capturedArity;
267 receiverClass = factoryType.parameterType(0);
268 }
269
270 // check receiver type
271 if (!implClass.isAssignableFrom(receiverClass)) {
272 throw new LambdaConversionException(
273 String.format("Invalid receiver type %s; not a subtype of implementation type %s",
274 receiverClass.descriptorString(), implClass.descriptorString()));
275 }
276 } else {
277 // no receiver
278 capturedStart = 0;
279 samStart = capturedArity;
280 }
281
282 // Check for exact match on non-receiver captured arguments
283 for (int i=capturedStart; i<capturedArity; i++) {
284 Class<?> implParamType = implMethodType.parameterType(i);
285 Class<?> capturedParamType = factoryType.parameterType(i);
286 if (!capturedParamType.equals(implParamType)) {
287 throw new LambdaConversionException(
288 String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
289 i, capturedParamType, implParamType));
290 }
291 }
292 // Check for adaptation match on non-receiver SAM arguments
293 for (int i=samStart; i<implArity; i++) {
294 Class<?> implParamType = implMethodType.parameterType(i);
354 // both are primitive: widening
355 Wrapper wto = forPrimitiveType(toType);
356 return wto.isConvertibleFrom(wfrom);
357 } else {
358 // from primitive to reference: boxing
359 return toType.isAssignableFrom(wfrom.wrapperType());
360 }
361 } else {
362 if (toType.isPrimitive()) {
363 // from reference to primitive: unboxing
364 Wrapper wfrom;
365 if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
366 // fromType is a primitive wrapper; unbox+widen
367 Wrapper wto = forPrimitiveType(toType);
368 return wto.isConvertibleFrom(wfrom);
369 } else {
370 // must be convertible to primitive
371 return !strict;
372 }
373 } else {
374 // fromType should be a superclass of toType
375 return !strict || toType.isAssignableFrom(fromType);
376 }
377 }
378 }
379
380 /**
381 * Check type adaptability for return types --
382 * special handling of void type) and parameterized fromType
383 * @return True if 'fromType' can be converted to 'toType'
384 */
385 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
386 return toType.equals(void.class)
387 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
388 }
389 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
390 if (fromType.equals(void.class) || toType.equals(void.class)) return fromType.equals(toType);
391 else return isAdaptableTo(fromType, toType, true);
392 }
393
394
|