Working with Java Wildcard Generics

79 views
Skip to first unread message

Nick

unread,
Jul 22, 2015, 1:46:00 PM7/22/15
to ceylon-users
I'm having trouble getting writing a function that will operate on Java types that extend java.lang.Comparable as follows

// Java class that operates on java.lang.Comparable

public class A<T extends Comparable> {}


// Ceylon code to work with above Java type

import java.lang {Comparable}

import java.time {LocalDateTime}


A<T> bar<T>(A<T> t) given T satisfies Comparable<Object> {...}


void test() {

    bar<LocalDateTime>(A<LocalDateTime>()); <============= Error [Type parameter T of declaration bar has argument LocalDateTime not assignable to upper bound Comparable<Object> of T]

}



My gut says my function definition should really be:


A<Tbar<T>(A<Ttgiven T satisfies Comparable<out Object> {...}


But Ceylon doesn't support this.  Is there a way to work around this?  I don't have control over the Java lib I'm using; so A cannot be modified.



Thanks.

Tako Schotanus

unread,
Jul 22, 2015, 5:09:23 PM7/22/15
to ceylon...@googlegroups.com

On Wed, Jul 22, 2015 at 7:08 PM, Nick <nick...@gmail.com> wrote:
A<T> bar<T>(A<T> t) given T satisfies Comparable<Object> {...}

Can't you do "satisfies Comparable<T>" for your use-case?


-Tako

Nick

unread,
Jul 22, 2015, 8:35:05 PM7/22/15
to ceylon-users, ta...@codejive.org
I tried that w/o any success (works with simple hierarchies like that for Double of Float).  But I had no luck with LocalDateTime or it's super interface ChronoLocalDateTime, which is what brings in Comparable.

This code has errors for the lines inicated:

import java.lang {Comparable,Double}

import java.time {LocalDateTime, LocalDate}

import java.time.chrono {ChronoLocalDateTime}


A<T> bar<out T>(A<T> t) given T satisfies Comparable<T> {

    return t;

}


void test() {

    bar<Double>(A<Double>());

    bar<LocalDateTime>(A<LocalDateTime>()); <=== Error [Type parameter T of declaration bar has argument LocalDateTime not assignable to upper bound Comparable<LocalDateTime> of T]

    bar<ChronoLocalDateTime<LocalDate>>(A<ChronoLocalDateTime<LocalDate>>()); <=== Error [Type parameter T of declaration bar has argument ChronoLocalDateTime<LocalDate> not assignable to upper bound Comparable<ChronoLocalDateTime<LocalDate>> of T]

Gavin King

unread,
Jul 22, 2015, 10:02:39 PM7/22/15
to ceylon...@googlegroups.com, Tako Schotanus
Whoah:

public interface ChronoLocalDateTime<D extends ChronoLocalDate>
extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>>

OMG!


So it looks like what you're really wanting to write is this:

A<T> bar<T>(A<T> t) given T satisfies Comparable<in T> => t;

i.e. the wildcard in the supertype of ChronoLocalDateTime is
obligating you to need a wildcard in the upper bound, which is
something Ceylon simply doesn't support, though it seems Java *does*.
(I never noticed that before.)

Open a feature request against ceylon-spec please, so that we can
investigate if we can/should allow wildcards in upper bound type
constraints.
> --
> You received this message because you are subscribed to the Google Groups
> "ceylon-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ceylon-users...@googlegroups.com.
> To post to this group, send email to ceylon...@googlegroups.com.
> Visit this group at http://groups.google.com/group/ceylon-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ceylon-users/c0efdb00-99c0-49ae-a30c-f182e62ecddd%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Gavin King
ga...@ceylon-lang.org
http://profiles.google.com/gavin.king
http://ceylon-lang.org
http://hibernate.org
http://seamframework.org

Nick

unread,
Jul 22, 2015, 11:51:21 PM7/22/15
to ceylon-users, ta...@codejive.org, gavin...@gmail.com
Thanks for the speedy reply.  This seems like a feature that would make Java interop much more seamless and less surprising.  I'll capture this in a feature request.

Gavin King

unread,
Jul 23, 2015, 3:38:50 AM7/23/15
to Nick, ceylon-users, Tako Schotanus
I'm not promising anything, OK? I'm really not sure how that would
impact the subtyping algorithms.

vincent beauseigneur

unread,
Jul 23, 2015, 7:13:14 AM7/23/15
to ceylon-users, nick...@gmail.com
By adding another type, like this :
A<T> bar<T, U>(A<T> t) given T satisfies Comparable<U> & U {...}

Comparable<X> seems to be seen neither as in nor out so...
I think it should success, but this add a type which has no other use.


On Wednesday, July 22, 2015 at 7:46:00 PM UTC+2, Nick wrote:

Nick

unread,
Jul 23, 2015, 10:37:24 AM7/23/15
to ceylon-users, vbeaus...@yahoo.fr
This isn't supported either and doesn't solve the issue.

A<T> bar<T, U>(A<T> t) given T satisfies Comparable<U> & U given U satisfies Object => t;


results in the following error: Type parameter upper bounds are not yet supported in combination with other bounds

vincent beauseigneur

unread,
Jul 23, 2015, 1:59:03 PM7/23/15
to ceylon-users, nick...@gmail.com
for a workaround for this special case you could configure bar like this (with 1.1.1 from 07/21) :
A<T|U> bar< T, U = LocalDateTime>(A<T|U> t)

  given T satisfies  Comparable<Object>
  given U satisfies LocalDateTime => t;
or specific class which directly extends ChronoLocalDate.

The default permits you to conserv your current syntax,

You may have to add check T or U, but it should works this time.

Or create a specific copy of bar for this very case (so with just U).

Ross Tate

unread,
Jul 23, 2015, 2:34:47 PM7/23/15
to ceylon...@googlegroups.com, nick...@gmail.com
LocalDateTime is not comparable with itself. This makes me suspect that A<LocalDateTime>() is not a valid input to bar, though I don't know what bar is so I can't assert that.

ChronoLocalDateTime<T> is a subtype of Comparable<ChronoLocalDateTime<T>> because it is a subtype of Comparable<ChronoLocalDateTime<?>> (due to inheritance), which is a subtype of Comparable<ChronoLocalDateTime<T>> due to contravariance because ChronoLocalDateTime<T> is a subtype of ChronoLocalDateTime<?> due to how wildcards work. Thus it doesn't sound like you need a new feature. Instead, you most likely have some glitch in importing types from Java.

--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceylon-users...@googlegroups.com.
To post to this group, send email to ceylon...@googlegroups.com.
Visit this group at http://groups.google.com/group/ceylon-users.

vincent beauseigneur

unread,
Jul 23, 2015, 3:15:49 PM7/23/15
to ceylon-users, nick...@gmail.com, ro...@ceylon-lang.org
My code here is just a workaround, not a correction it will probably work on previous version of Ceylon. It even will work well if only A interacts with U|T.

Comparable<ChronoLocalDateTime<?>> is NOT Comparable<ChronoLocalDateTime<T>> due to inheritance, it is just Comparable<ChronoLocalDateTime<?>>, it could be compared to all ChronoLocalDateTime whatever T and ? are.
As LocalDateTime is subtype of ChronoLocalDateTime<?>, it could be compared with itself (and all other ChronoLocalDateTime)...

Nick

unread,
Jul 23, 2015, 5:56:38 PM7/23/15
to ceylon-users, ro...@ceylon-lang.org, vbeaus...@yahoo.fr
To clarify, this following code does not compile with Ceylon IDE 1.1.1.v20150721-1337-Final.  The imports from Java are correct and verified.

import java.lang {Comparable,Double}

import java.time {LocalDateTime, LocalDate}

import java.time.chrono {ChronoLocalDateTime}



A<T> bar<T>(A<T> t) given T satisfies Comparable<T> => t;


void test() {

    bar<Double>(A<Double>());

    bar<LocalDateTime>(A<LocalDateTime>());

    bar<ChronoLocalDateTime<LocalDate>>(A<ChronoLocalDateTime<LocalDate>>());

vincent beauseigneur

unread,
Jul 24, 2015, 12:10:43 AM7/24/15
to ceylon-users, ro...@ceylon-lang.org, nick...@gmail.com
Well sorry, for my workaround to work you do not have to call bar<LocalDateTime> but bar<Comparable<Object>>, well in fact this also work well
A<T|LocalDateTime> bar< T>A<T|LocalDateTime> t)

  given T satisfies Comparable<Object>

replace LocalDateTime with ChronoLocalDateTime<LocalDate>, if you need.

Ross Tate

unread,
Jul 24, 2015, 12:29:41 AM7/24/15
to vincent beauseigneur, ceylon-users, Nicholas Eddy
I've moved the discussion to the issue you posted, since this is easier to discuss with markdown.
Reply all
Reply to author
Forward
0 new messages