Introduce Covariance/Contravariance at declaration site for Java 9 ?

Remi Forax forax at univ-mlv.fr
Sat Oct 27 03:19:52 PDT 2012


I've maybe found a solution :)

First, it's not possible to let the compiler do the transformation 
automagically because
in that case adding a default method to a function interface may break a 
lot of user code.
A function interface that is inherently co/contravariant should be 
declared as such in its declaration.

Removing the burden for the user to write wildcard is a nice goal, but 
it means that
the Java type system will be inherently more complex and it may not 
worth to add such
complexity for little benefit.

The issue is that users that creates API forget to add wildcards, so the 
practical solution is to
add a lint option to javac that warn user when they use a 
co/contravariant function interfaces
without specifying wildcards.
This solution doesn't change the type system so it can be implemented 
without pain and fear of corner cases.

Here is the proposal:
- adds two new type annotations (as defined by JSR308) in 
java.lang.annotation, Covariant and Contravariant,
that applies on type variables. These annotations are not inherited.
- add a new lint pass to javac that checks parameters of methods (not 
returns type, you should not use wildcards
on return type). If a type of a parameter is a parametrized type with 
type variables annotated with Covariant
(resp. contravariant), emit a warning is the parametrized type is not a 
? extends X (resp. ? super X).

so by example, the function interface Mapper will be declared:
   interface Mapper<@Covariant U, @Contravariant T> {
     public U map(T element);
   }
and Iterator and Iterable can be retrofitted like this:
   interface Iterator<@Covariant T> { ... }
   interface Iterable<@Covariant T> { ... }
but ListIterator, that inherits from Iterator can not have it's 
parameter T declared as covariant
because ListIterator defined methods add and set that takes a T as parameter
(that's why annotations @Covariant/@Contravariant should be declared are 
not inheritable).

now if in a class there is a method declared like this:
   static <T, U> Iterator<U> mapIterator(Iterator<T> iterator, Mapper<U, 
T> mapper) { ... }
the compiler will emit two warnings because the parameter iterator 
should be an Iterator<? extends T>
and mapper should be a Mapper<? extends U, ? super T>.

The only open question is does lint should accept to tag a type 
parameter with @Covariant/@Contravariant
even if the type parameter appear in method of the interface at position 
it should not. C# does that.

cheers,
Rémi

On 10/18/2012 09:25 PM, Kevin Bourrillion wrote:
> FTR, I agree fairly strongly with everything Dan says here.
>
>
> On Thu, Oct 18, 2012 at 12:20 PM, Dan Smith <daniel.smith at oracle.com 
> <mailto:daniel.smith at oracle.com>> wrote:
>
>     I think it's a good idea, at least worth serious consideration.
>
>     There would be no _requirement_ to design libraries in
>     declaration-site-friendly ways, but the fact is we already have
>     _lots_ of types that are inherently co-/contra- variant, and the
>     "right" way to use those types is to always use a wildcard.  It
>     turns into a mechanical transformation that obscures the code
>     behind layers of wildcards and pointlessly punishes users if they
>     mess up; it would sure be nice to remove that burden from clients
>     of variant types.
>
>     Anyway, I can say it's on the radar.  But maybe we will conclude
>     it's a horrible idea; or maybe other things will take priority.
>
>     —Dan
>
>     On Oct 15, 2012, at 6:24 PM, Joshua Bloch <josh at bloch.us
>     <mailto:josh at bloch.us>> wrote:
>
>     > I believe that declaration site variance annotations are every
>     bit as bad as use-site annotations.  They're bad in a different
>     way--they force you to write idiosyncratic types because natural
>     types don't lend themselves to fixed variance restrictions--but
>     they're still bad. Providing both use and declaration site
>     variance in one language is the worst of both worlds (unless
>     you're trying to kill the language).
>     >
>     >     Josh
>     >
>     > On Mon, Oct 15, 2012 at 3:09 PM, Remi Forax <forax at univ-mlv.fr
>     <mailto:forax at univ-mlv.fr>> wrote:
>     > I've just read the presentation of Stuart Marks at JavaOne [1],
>     > all examples after slide 32, the first one that use lambdas are
>     not written correctly
>     > because all method signatures do not use wildcards.
>     >
>     > Brian, I know that we will not be able to introduce
>     covariance/contravariance
>     > at declaration site for Java 8, so the solution we will deliver
>     will be far from perfect
>     > because nobody understand wildcards.
>     > Is there a way to free Dan and Maurizio  enough time to
>     investigate if
>     > covariance/contravariance can be added to Java 9.
>     >
>     > Rémi
>     > [1]
>     https://stuartmarks.wordpress.com/2012/10/07/javaone-2012-jump-starting-lambda-programming/
>     >
>     >
>
>
>
>
> -- 
> Kevin Bourrillion | Java Librarian | Google, Inc. |kevinb at google.com 
> <mailto:kevinb at google.com>
>



More information about the lambda-libs-spec-observers mailing list