IterableOnce vs Iterator binary compatibility

Hi.

IterableOnce was kept purposely minimal so that external libraries may easily be interoperable with the standard collection library, but do not depend on its APIs. For some time, I assumed that it also meant that it will be kept binary compatible for much longer than the collection framework itself - after all, it has only two methods which seem unintrusive. However, it returns an Iterator, and the latter extends IterableOnceOps, which has a boat load of methods, and likely doesn’t come with binary compatibility guarantees stronger than the rest of the collection library. A collection implementing IterableOnce therefore has to implement also its own Iterator (unless it is able to just depend on the implementations already provided by the library, which is unlikely if it does not wish to integrate deeper by extending some more specific collection interface). This will make it binary incompatible as soon as IterableOnceOps becomes binary incompatible (I assume here that Iteratoritself won’t break the compatibility, as it was kept purposely minimal.

I am still educating myself on binary compatibility - it is a huge topic, dependent on JVM implementations - but I wonder about the intent of the authors in that matter. It also seems to me that having some GenericIterator extends IterableOnce supertype of Iterator, which defines only next and hasNext, and using it instead of Iterator in IterableOnce would be a good idea to adopt for the collection library in the future, as it would solve this problem with little to no effort and maintainance burden.

Everything in the standard library has the same binary compatibility guarantees. And those guarantees are: we don’t break anything in 3.x. Breaking something would require a Scala 4, which won’t happen in the foreseeable future.

2 Likes

Does it mean a commitment to no non backwards compatible changes to scala.collections, like those in 2.12?

All the details are here:

Does it mean a commitment to no non backwards compatible changes to scala.collections, like those in 2.12?

Yes it does. SIP-51 drops forward compatibility, so e.g. if you’re compiling against std lib 2.13.14 you cannot use a library linking to 2.13.18.

But you can always safely upgrade std lib while linking to libraries relying on older std lib, e.g. using 2.13.16 and a library compiled against 2.13.2 is fine. Backward compatibility of std lib is guaranteed.

Scala 3 inherits 2.13’s std lib (+ some things extra) so it inherits its contracts.