[External] : The introduction of Sequenced collections is not a source compatible change
Stuart Marks
stuart.marks at oracle.com
Thu May 4 22:45:51 UTC 2023
The introduction of Sequenced Collections in JDK 21+20 did make a difference in this
specific case. One can compile Rémi's example on JDK 21+19 successfully, but it will
fail on JDK 21+20.
Here's Rémi's 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);
}
The type of 'factories' is inferred to be a List of the /something/ which is the
common supertype (least upper bound, or LUB) of the arguments. It's pretty easy to
see this in an IDE or in jshell. In JDK 21+19 factories is inferred to have this type:
List<Supplier<? extends Map<String,String>>>
whereas in JDK 21+20 it's inferred to have this type:
List<Supplier<? extends SequencedMap<String,String>>>
Rémi's example carefully defined the parameter of the m() method so that it matches
the first (and compiles successfully) but does not match the second (and so fails
with a compilation error).
This isn't a bug in type inference or in Sequenced Collections. It's a consequence
of a few phenomena: 1) the result of type inference depends on the exact inputs
given; 2) the result of type inference depends on the current type hierarchy; 3)
it's possible to write source code that implicitly depends on a specific result of
type inference. Sequenced Collections changed the type hierarchy, so inference gave
different results, and the example depended on getting a specific result under JDK
21+19.
When you changed the code to List.of(supplier1), this changed the inputs to type
inference, so it got a different result:
List<Supplier<LinkedHashMap<String,String>>>
This doesn't match the parameter of the m() method, so this gives a compilation
error on all versions of the system.
As you observed, changing the declaration of m() to be:
public static void m(List<? extends Supplier<? extends Map<String, String>>>
factories)
This lets the examples compile on JDK 21+19 and JDK 21+20, whether List.of() is
given one or both arguments. This change broadens the set of types accepted by m(),
reducing its specific dependency on a specific arrangement of the type hierarchy.
It's also probably a good idea in general, as we recommend using wildcard variance
(? extends T) consistently in order to increase the flexibility of methods. For
example, I might have a MySupplier functional interface that adds some features to
the built-in Supplier interface:
interface MySupplier<T> extends Supplier<T> {
// more features
}
If the suppliers were declared as instances of MySupplier instead, Rémi's example
would fail even on JDK 21+19. So yes, in a sense, this doesn't have much to do with
the introduction of Sequenced Collections.
s'marks
On 5/2/23 5:09 AM, Blaise B. wrote:
>
> Hello,
>
> I've tested the example provided by Rémi, and it looks like the compile-time error
> has little to do with the integration of Sequenced Collections into mainline.
> By changing the "factories" list to contain only one element instead of two, the
> code does not compile even in previous jdk versions (tested on jdk 17, 18, 19, 20,
> 21):
>
> import java.util.*;
> import java.util.function.Supplier;
>
> public class SequencedCollectionsTest {
>
> 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);
> var factories = List.of(supplier1);
>
> m(factories);
> }
> }
>
> It all only compiles on all versions when I change the signature of the method m() to:
>
> public static void m(List<? extends Supplier<? extends Map<String,
> String>>> factories) {
> }
>
> So unless there are more other cases of failing compiles, it seems to me like
> something was actually fixed in the latest jdk21 build, and that the integration
> of Sequenced Collections was just coincidence.
>
> Hope this helps.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20230504/edcec4d3/attachment-0001.htm>
More information about the core-libs-dev
mailing list