Introduce Covariance/Contravariance at declaration site for Java 9 ?
Brian Goetz
brian.goetz at oracle.com
Sat Oct 27 09:22:28 PDT 2012
This is definitely worthy of exploration. And, the good news is, it can
be entirely implemented using a JSR-308 checker -- so (at least
initially) no javac changes are required to develop and validate the
concept. This fits nicely into the use of annotations as a means of
capturing design intent, and enabling tools to verify design intent.
(Its bad enough we make these mistakes; its worse that some of these
then cannot be corrected because of compatibility concerns.)
On 10/27/2012 6:19 AM, Remi Forax wrote:
> 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-experts
mailing list