JEP 300 - casting with declaration-site variance

Attila Kelemen attila.kelemen85 at gmail.com
Wed Mar 5 12:34:22 UTC 2025


Actually, I have realized that there are realistic methods that would fall
into this problem. In fact, with pattern matching, it is also a question
how the JEP will plan to retain source compatibility, because a method
might this could realistically exist:

```
<T> boolean contains(Iterable<T> itr, T element) {
  return itr instanceof Collection<T> c
    ? c.contains(element)
    : iterableContains(itr, element); // impl of iterableContains omitted
}
```

One could argue that the implementor should have used `? extends T` here,
but (as even the JEP admits) people are often lazy (or just lack knowledge)
and will not write `? extends`.

If it was on me, I would allow the above unsafe construct in the JEP, but
would issue some kind of unsafe cast warning.


Attila Kelemen <attila.kelemen85 at gmail.com> ezt írta (időpont: 2025. márc.
4., K, 20:51):

> Hi,
>
> I have read JEP 300, and it seems it is not defining what it intends to do
> with casting these adjusted types to a subtype. For example consider the
> following method:
>
> ```
> <T> void method1(Iterable<T> itr) {
>   if (itr instanceof List) {
>     var list = (List<T>) itr;
>     list.add(null);
>   }
> }
> ```
>
> The cast in the above example is safe (it doesn't emit any unsafe cast
> warning). However, if `Iterable` becomes covariant at the declaration site,
> then the above code is now unsafe.
>
> What is the plan of the JEP with such casting? Will it make the above cast
> unsafe? If so, then there will be no way to safely cast from `Iterable<T>`
> to `List<T>`. Admittedly, I can't recall any code I have ever seen where
> this would be a problem (and so I wouldn't worry about it too much), but it
> would be nice if the JEP would explicitly address this question.
>
> In Kotlin, they allow such unsafe casts without a warning (in fact, you
> don't even need a cast in Kotlin for it). For example, the following code
> compiles without warning in Kotlin:
>
> ```
> fun evilMethod(list: List<Any>) {
>   if (list is MutableList) {
>     list.add("hello")
>   }
> }
>
> fun naiveMethod() {
>   val list = mutableListOf<Int>()
>   evilMethod(list)
>   println(list.sum())
> }
> ```
>
> Of course, calling `naiveMethod` fails with an exception when trying to
> call `sum`. (Note: `List` in Kotlin is a "read-only" variant of Java's
> List, and MutableList is the equivalent of Java's List interface).
>
> I personally don't like the behavior of Kotlin, and would rather choose
> that only `Iterable<T>` to `List<? extends T>` is safe from here onwards.
>
> Attila
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20250305/19d1ce69/attachment.htm>


More information about the compiler-dev mailing list