jdk/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
changeset 43700 ee6b5bd26bf9
parent 25859 3317bb8137f4
child 43702 699ccfe75625
equal deleted inserted replaced
43699:9127aa5e51a7 43700:ee6b5bd26bf9
   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();