Introduce Covariance/Contravariance at declaration site for Java 9 ?
Andrey Breslav
andrey.breslav at jetbrains.com
Sat Oct 27 09:35:16 PDT 2012
Looks like a decent practical solution. An IDE would make it a breeze to put all those wildcards in.
On Oct 27, 2012, at 20:22 , Brian Goetz wrote:
> 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>
>>>
>>
--
Andrey Breslav
http://jetbrains.com
Develop with pleasure!
More information about the lambda-libs-spec-experts
mailing list