Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8254571

Erroneous generic type inference in a lambda expression with a checked exception

XMLWordPrintable

    • 9
    • b28
    • generic
    • generic

        ADDITIONAL SYSTEM INFORMATION :
        Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.8+10-LTS, mixed mode)

        A DESCRIPTION OF THE PROBLEM :
        A regression occurred when I migrated my code from java 8 to java 11, and javac 11 compiler report an error now systematically
         

        REGRESSION : Last worked in version 8

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        compiling project with a javac 11.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        compiler must infer correct lambda return type and throws exception without errors
        ACTUAL -
        unreported exception IOException; must be caught or declared to be thrown
                        .map(Lambda.function(resource -> Mapper.toString(resource),
                                                                        ^
        1 error

        ---------- BEGIN SOURCE ----------
        import java.io.IOException;
        import java.io.InputStream;
        import java.util.ArrayList;
        import java.util.List;
        import java.util.function.BiFunction;
        import java.util.function.Function;

        class BugGenericSneakyThrowInference {
            public static void main(String[] args) {
                process(new ArrayList<>());
            }

            public static String[] process(List<Resource> resources) {

                return resources.stream()
                        .map(Lambda.function(resource -> Mapper.toString(resource),
                                (res, ex) -> Lambda.sneakyThrow(ex)))
                        .toArray(String[]::new);

            }
        }

        interface Resource {

            InputStream getInputStream() throws IOException;
        }

        interface Function1<T, R> extends Function<T, R> {

            interface WithException<T, R, E extends Throwable> {

                R apply(T t) throws E;

                default Function1<T, R> cast(BiFunction<T, Throwable, R> fn) {
                    return t -> {
                        try {
                            return apply(t);
                        } catch (Throwable e) {
                            return fn.apply(t, e);
                        }
                    };
                }
            }
        }

        final class Lambda {

            public static <T, R, E extends Throwable> Function<T, R> function(Function1.WithException<T, R, E> function,
                    BiFunction<T, Throwable, R> errorFn) {
                return function.cast(errorFn);
            }

            @SuppressWarnings("unchecked")
            public static <R, E extends Throwable> R sneakyThrow(Throwable e) throws E {
                throw (E) e;
            }

        }

        class Mapper {

            static String toString(Resource resource) throws IOException {
                return resource.getInputStream().toString();
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        public static String[] process(List<Resource> resources) {
                return resources.stream()
                        .map(Lambda.function((Function1.WithException<Resource, String, IOException>)(resource -> Mapper.toString(resource)),
                                (res, ex) -> Lambda.sneakyThrow(ex)))
                        .toArray(String[]::new);

            }

        FREQUENCY : always


              vromero Vicente Arturo Romero Zaldivar
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: