Project Coin: Inducing contributory heap pollution
By darcy on Jun 09, 2010
US patent law defines various kinds of patent infringement, as do other jurisdictions. (I am not a lawyer! This is not legal advice! Check your local listings! Don't kill kittens! Example being used for analogy purposes only! ) One can infringe on a patent directly, say, by making, using, selling, offering to sell, or importing a patented widget without a suitable license. A computer scientist looking to infringe might (erroneously) believe the conditions for infringement can be circumvented by applying the familiar technique of adding a level of indirection. For example, one indirection would be selling 90% percent of the patented widget, leaving the end-user to complete the final 10% and thereby infringe. Such contributory infringement is also verboten. Likewise, providing step-by-step instructions on how to infringe the patent is outlawed as inducing infringement. Putting both techniques together, inducing contributory infringement is also disallowed.
Starting in JDK 5, a compiler must issue mandatory unchecked warnings at sites of possible heap pollution:
Java Language Specification, Third Edition — §18.104.22.168 Heap Pollution
It is possible that a variable of a parameterized type refers to an object that is not of that parameterized type. This situation is known as heap pollution. This situation can only occur if the program performed some operation that would give rise to an unchecked warning at compile-time.
One case where unchecked warnings occur is a call to a varargs method where the type of the variable argument is not reifiable. That is, where the type information for the parameter is not fully expressible at runtime due to the erasure of generics. Varargs are implemented using arrays and arrays are reified; that is, the component type of an array is stored internally and used when needed for various type checks at runtime. However, the type information stored for an array's component type cannot store the information needed to represent a non-reifiable parameterized type.
The mismatch between reified arrays being used to pass non-reified (and non-reifiable) parameterized types is the basis for the unchecked warnings when such conflicted methods are called. However in JDK 5, only calling one of conflicted methods causes a compile-time warning; declaring such a method doesn't lead to any similar warning. This is analogous to the compiler only warning of direct patent infringement, while ignoring or being oblivious too indirect infringement. While the mere existence of a conflicted varargs method does not cause heap pollution per se, its existence contributes to heap pollution by providing an easy way to cause heap pollution to occur and induces heap pollution by offering the method to be called. By this reasoning, if method calls that cause heap pollution deserve a compiler warning, so do method declarations which induce contributory heap pollution.
Additionally, the warnings issued for some calls to varargs methods involving heap pollution are arguably spurious since nothing bad happens. For example, calling various useful helper varargs methods in the platform trigger unchecked warnings, including:
public static <T> List<T> Arrays.asList(T... a)
public static <T> boolean Collections.addAll(Collection<? super T> c, T... elements)
public static <E extends Enum<E>> EnumSet<E> EnumSet.of(E first, E... rest)
These three methods all iterate over the varargs array pulling out the elements in turn and processing them. If the varargs array is constructed by the compiler using proper type inference, the bodies of the methods won't experience any
ClassCastExceptions due to handling of the array's elements.
Currently, to eliminate the warnings associated with calling these methods, each call site needs a
To address these usability issues with varargs, Project Coin accepted simplifying varargs as one if the project's changes. The initial prototype version of this feature pushed by Maurizio, has several parts:
A new mandatory compiler warning is generated on declaration sites of problematic varargs methods that are able to induce contributory heap pollution.
The ability to suppress those mandatory warnings at a declaration site using an
@SuppressWarnings("varargs")annotation. The warnings may also be suppressing using the
-Xlint:-varargsoption to the compiler.
@SuppressWarnings("varargs")annotation is used on a problematic varargs method declaration, the unchecked warnings at call sites of that method are also suppressed.
This prototype will allow experience to be gained with the algorithms to detect and suppress the new mandatory warnings. However, the annotation used to suppress the warnings should be part of the varargs method's contract, denoting that when a compiler-constructed array is passed to the method nothing bad will happen, for a suitable definition of nothing bad. Therefore, an
@Documented annotation type needs to be used for this purpose and
SuppressWarnings is not
@Documented. Additionally, the suppressing annotation for varags should also be
@Inherited so the method implementation restrictions are passed on to subclasses.
Subsequent design discussions about the new annotation type with the properties in question to suppress the varargs warnings as well as criteria for the annotation to be correctly applied can occur on the Project Coin mailing list.