-
Bug
-
Resolution: Unresolved
-
P3
-
8, 9, 10, 10.0.1, 11
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
Local inner classes in generic methods should be treated as generic types: casts to them should be unchecked and they should not be allowed to extend Throwable. I suspect this is a problem in the JLS.
See included examples demonstrating this as a type system loophole: there are no unchecked warnings, yet this causes heap pollution. The first example shows that such a cast should be treated as unchecked, and the second that it's not safe to allow such a local inner class in a generic method to extend Throwable.
This (and other bugs) comes from this blog post: http://wouter.coekaerts.be/2018/java-type-system-broken
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile and run the code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
unchecked warnings or compilation errors
ACTUAL -
heap pollution, ClassCastException
---------- BEGIN SOURCE ----------
public class LocalInnerClass {
static Object prev;
static <T> T go(T t) {
class A extends ArrayList<T> { }
if (prev == null) { // first execution
A a = new A();
a.add(t);
prev = a;
return null;
} else { // second execution
return ((A) prev).get(0);
}
}
public static void main(String[] args) {
go(1);
String s = go(""); // ClassCastException
}
}
public class LocalInnerClassWithException {
static <T> T go(T in, Object other) {
class A extends RuntimeException {
T t;
}
if (other != null) { // first execution
try {
go(other, null);
} catch (A a) {
return a.t; // returns other
}
throw new AssertionError(); // unreachable
} else {
A a = new A();
a.t = in;
throw a;
}
}
public static void main(String[] args) {
String s = go("", 1); // ClassCastException
}
}
---------- END SOURCE ----------
FREQUENCY : always
Local inner classes in generic methods should be treated as generic types: casts to them should be unchecked and they should not be allowed to extend Throwable. I suspect this is a problem in the JLS.
See included examples demonstrating this as a type system loophole: there are no unchecked warnings, yet this causes heap pollution. The first example shows that such a cast should be treated as unchecked, and the second that it's not safe to allow such a local inner class in a generic method to extend Throwable.
This (and other bugs) comes from this blog post: http://wouter.coekaerts.be/2018/java-type-system-broken
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile and run the code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
unchecked warnings or compilation errors
ACTUAL -
heap pollution, ClassCastException
---------- BEGIN SOURCE ----------
public class LocalInnerClass {
static Object prev;
static <T> T go(T t) {
class A extends ArrayList<T> { }
if (prev == null) { // first execution
A a = new A();
a.add(t);
prev = a;
return null;
} else { // second execution
return ((A) prev).get(0);
}
}
public static void main(String[] args) {
go(1);
String s = go(""); // ClassCastException
}
}
public class LocalInnerClassWithException {
static <T> T go(T in, Object other) {
class A extends RuntimeException {
T t;
}
if (other != null) { // first execution
try {
go(other, null);
} catch (A a) {
return a.t; // returns other
}
throw new AssertionError(); // unreachable
} else {
A a = new A();
a.t = in;
throw a;
}
}
public static void main(String[] args) {
String s = go("", 1); // ClassCastException
}
}
---------- END SOURCE ----------
FREQUENCY : always
- relates to
-
JDK-8030746 4.10: Define subtyping for inner classes of parameterized types
- Open