139 this.instantiatedMethodType = instantiatedMethodType; |
139 this.instantiatedMethodType = instantiatedMethodType; |
140 this.isSerializable = isSerializable; |
140 this.isSerializable = isSerializable; |
141 this.markerInterfaces = markerInterfaces; |
141 this.markerInterfaces = markerInterfaces; |
142 this.additionalBridges = additionalBridges; |
142 this.additionalBridges = additionalBridges; |
143 |
143 |
|
144 if (samMethodName.isEmpty() || |
|
145 samMethodName.indexOf('.') >= 0 || |
|
146 samMethodName.indexOf(';') >= 0 || |
|
147 samMethodName.indexOf('[') >= 0 || |
|
148 samMethodName.indexOf('/') >= 0 || |
|
149 samMethodName.indexOf('<') >= 0 || |
|
150 samMethodName.indexOf('>') >= 0) { |
|
151 throw new LambdaConversionException(String.format( |
|
152 "Method name '%s' is not legal", |
|
153 samMethodName)); |
|
154 } |
|
155 |
144 if (!samBase.isInterface()) { |
156 if (!samBase.isInterface()) { |
145 throw new LambdaConversionException(String.format( |
157 throw new LambdaConversionException(String.format( |
146 "Functional interface %s is not an interface", |
158 "Functional interface %s is not an interface", |
147 samBase.getName())); |
159 samBase.getName())); |
148 } |
160 } |
273 Class<?> expectedType = instantiatedMethodType.returnType(); |
285 Class<?> expectedType = instantiatedMethodType.returnType(); |
274 Class<?> actualReturnType = |
286 Class<?> actualReturnType = |
275 (implKind == MethodHandleInfo.REF_newInvokeSpecial) |
287 (implKind == MethodHandleInfo.REF_newInvokeSpecial) |
276 ? implDefiningClass |
288 ? implDefiningClass |
277 : implMethodType.returnType(); |
289 : implMethodType.returnType(); |
278 Class<?> samReturnType = samMethodType.returnType(); |
|
279 if (!isAdaptableToAsReturn(actualReturnType, expectedType)) { |
290 if (!isAdaptableToAsReturn(actualReturnType, expectedType)) { |
280 throw new LambdaConversionException( |
291 throw new LambdaConversionException( |
281 String.format("Type mismatch for lambda return: %s is not convertible to %s", |
292 String.format("Type mismatch for lambda return: %s is not convertible to %s", |
282 actualReturnType, expectedType)); |
293 actualReturnType, expectedType)); |
283 } |
294 } |
284 if (!isAdaptableToAsReturnStrict(expectedType, samReturnType)) { |
295 |
285 throw new LambdaConversionException( |
296 // Check descriptors of generated methods |
286 String.format("Type mismatch for lambda expected return: %s is not convertible to %s", |
297 checkDescriptor(samMethodType); |
287 expectedType, samReturnType)); |
|
288 } |
|
289 for (MethodType bridgeMT : additionalBridges) { |
298 for (MethodType bridgeMT : additionalBridges) { |
290 if (!isAdaptableToAsReturnStrict(expectedType, bridgeMT.returnType())) { |
299 checkDescriptor(bridgeMT); |
291 throw new LambdaConversionException( |
300 } |
292 String.format("Type mismatch for lambda expected return: %s is not convertible to %s", |
301 } |
293 expectedType, bridgeMT.returnType())); |
302 |
294 } |
303 /** Validate that the given descriptor's types are compatible with {@code instantiatedMethodType} **/ |
295 } |
304 private void checkDescriptor(MethodType descriptor) throws LambdaConversionException { |
296 } |
305 for (int i = 0; i < instantiatedMethodType.parameterCount(); i++) { |
|
306 Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i); |
|
307 Class<?> descriptorParamType = descriptor.parameterType(i); |
|
308 if (!descriptorParamType.isAssignableFrom(instantiatedParamType)) { |
|
309 String msg = String.format("Type mismatch for instantiated parameter %d: %s is not a subtype of %s", |
|
310 i, instantiatedParamType, descriptorParamType); |
|
311 throw new LambdaConversionException(msg); |
|
312 } |
|
313 } |
|
314 |
|
315 Class<?> instantiatedReturnType = instantiatedMethodType.returnType(); |
|
316 Class<?> descriptorReturnType = descriptor.returnType(); |
|
317 if (!isAdaptableToAsReturnStrict(instantiatedReturnType, descriptorReturnType)) { |
|
318 String msg = String.format("Type mismatch for lambda expected return: %s is not convertible to %s", |
|
319 instantiatedReturnType, descriptorReturnType); |
|
320 throw new LambdaConversionException(msg); |
|
321 } |
|
322 } |
297 |
323 |
298 /** |
324 /** |
299 * Check type adaptability for parameter types. |
325 * Check type adaptability for parameter types. |
300 * @param fromType Type to convert from |
326 * @param fromType Type to convert from |
301 * @param toType Type to convert to |
327 * @param toType Type to convert to |
343 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) { |
369 private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) { |
344 return toType.equals(void.class) |
370 return toType.equals(void.class) |
345 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false); |
371 || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false); |
346 } |
372 } |
347 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) { |
373 private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) { |
348 if (fromType.equals(void.class)) return toType.equals(void.class); |
374 if (fromType.equals(void.class) || toType.equals(void.class)) return fromType.equals(toType); |
349 return isAdaptableTo(fromType, toType, true); |
375 else return isAdaptableTo(fromType, toType, true); |
350 } |
376 } |
351 |
377 |
352 |
378 |
353 /*********** Logging support -- for debugging only, uncomment as needed |
379 /*********** Logging support -- for debugging only, uncomment as needed |
354 static final Executor logPool = Executors.newSingleThreadExecutor(); |
380 static final Executor logPool = Executors.newSingleThreadExecutor(); |