The introduction of Sequenced collections is not a source compatible change
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Sat May 6 00:41:46 UTC 2023
Another way to help inference, in cases like this would be to break up
the method chain - as follows:
final Stream<Collection<String>> stream = Stream.of(nestedDequeue,
nestedList);
final List<Collection<String>> list = stream.toList();
In the above rewriting, now the target type Stream<Collection<String>>
"drives" inference for Stream::of - meaning that inference will pick the
"correct" supertype.
The problem with the original example is that the target type applies to
the Stream::toList() call, and the call to Stream::of is type-checked in
a bottom-up fashion, w/o any influence from the target-type.
This is, unfortunately, a known limitation of the inference scheme
specified in the JLS and implemented by javac.
So, in a way, both the `var` example and this one are similar in spirit,
as they both try to compute the least upper bound between two
collections, in a situation where no target type is available: in one
case, trivially, because the target is `var`; in the other case because
the target doesn't "flow" to the method call that would require it the most.
Maurizio
On 04/05/2023 14:23, Raffaello Giulietti wrote:
> Without changing the semantics at all, you could also write
>
> final List<Collection<String>> list =
> Stream.<Collection<String>>of(nestedDequeue, nestedList).toList();
>
> to "help" type inference.
>
>
>
>
> On 2023-05-03 15:12, forax at univ-mlv.fr wrote:
>> Another example sent to me by a fellow French guy,
>>
>> final Deque<String> nestedDequeue = new ArrayDeque<>();
>> nestedDequeue.addFirst("C");
>> nestedDequeue.addFirst("B");
>> nestedDequeue.addFirst("A");
>>
>> final List<String> nestedList = new ArrayList<>();
>> nestedList.add("D");
>> nestedList.add("E");
>> nestedList.add("F");
>>
>> final List<Collection<String>> list = Stream.of(nestedDequeue,
>> nestedList).toList();
>>
>> This one is cool because no 'var' is involved and using
>> collect(Collectors.toList()) instead of toList() solves the inference
>> problem.
>>
>> Rémi
>>
>> ----- Original Message -----
>>> From: "Stuart Marks" <stuart.marks at oracle.com>
>>> To: "Remi Forax" <forax at univ-mlv.fr>
>>> Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>
>>> Sent: Tuesday, May 2, 2023 2:44:28 AM
>>> Subject: Re: The introduction of Sequenced collections is not a
>>> source compatible change
>>
>>> Hi Rémi,
>>>
>>> Thanks for trying out the latest build!
>>>
>>> I'll make sure this gets mentioned in the release note for Sequenced
>>> Collections.
>>> We'll also raise this issue when we talk about this feature in the
>>> Quality
>>> Outreach
>>> program.
>>>
>>> s'marks
>>>
>>> On 4/29/23 3:46 AM, Remi Forax wrote:
>>>> I've several repositories that now fails to compile with the latest
>>>> jdk21, which
>>>> introduces sequence collections.
>>>>
>>>> The introduction of a common supertype to existing collections is
>>>> *not* a source
>>>> compatible change because of type inference.
>>>>
>>>> Here is a simplified example:
>>>>
>>>> public static void m(List<Supplier<? extends Map<String,
>>>> String>>> factories) {
>>>> }
>>>>
>>>> public static void main(String[] args) {
>>>> Supplier<LinkedHashMap<String,String>> supplier1 =
>>>> LinkedHashMap::new;
>>>> Supplier<SortedMap<String,String>> supplier2 = TreeMap::new;
>>>> var factories = List.of(supplier1, supplier2);
>>>> m(factories);
>>>> }
>>>>
>>>>
>>>> This example compiles fine with Java 20 but report an error with
>>>> Java 21:
>>>> SequencedCollectionBug.java:28: error: method m in class
>>>> SequencedCollectionBug
>>>> cannot be applied to given types;
>>>> m(factories);
>>>> ^
>>>> required: List<Supplier<? extends Map<String,String>>>
>>>> found: List<Supplier<? extends SequencedMap<String,String>>>
>>>> reason: argument mismatch; List<Supplier<? extends
>>>> SequencedMap<String,String>>>
>>>> cannot be converted to List<Supplier<? extends
>>>> Map<String,String>>>
>>>>
>>>>
>>>>
>>>> Apart from the example above, most of the failures I see are in the
>>>> unit tests
>>>> provided to the students, because we are using a lot of 'var' in
>>>> them so they
>>>> work whatever the name of the types chosen by the students.
>>>>
>>>> Discussing with a colleague, we also believe that this bug is not
>>>> limited to
>>>> Java, existing Kotlin codes will also fail to compile due to this bug.
>>>>
>>>> Regards,
>>>> Rémi
More information about the core-libs-dev
mailing list