-
Bug
-
Resolution: Fixed
-
P3
-
11, 14, 15, 16
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8269443 | 18 | Vicente Arturo Romero Zaldivar | P3 | Resolved | Fixed | b04 |
JDK-8270630 | 17.0.1 | Vicente Arturo Romero Zaldivar | P3 | Resolved | Fixed | b03 |
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
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
- backported by
-
JDK-8269443 Erroneous generic type inference in a lambda expression with a checked exception
- Resolved
-
JDK-8270630 Erroneous generic type inference in a lambda expression with a checked exception
- Resolved
- relates to
-
JDK-8066974 Compiler doesn't infer method's generic type information in lambda body
- Closed