When publishing a library with SBT, you can choose a CrossVersion, which controls which parts of the Scala version number, if any, are appended to the module id, so one can use the %% syntax we all know and love.
AFAICT, there is currently no CrossVersion for the minor part of the Scala version. There is disabled, patch, full, … but not minor. I think it would be useful to add it. Here’s a use case:
I want to publish a library that helps you inspect trees inside your Scala 3 reflect macros. I can’t just publish it for _3 and use the latest LTS, because someone might want to use the library to inspect trees in newer versions of Scala which might have new features. For example, the JavaAnnotation flag on symbols or the FlexibleType type in the reflect module are both not yet available in Scala 3.3.x
On the other hand, I obviously can’t publish for _3 and target the newest version, because people might want to use it on codebases of older versions, such as the latest LTS.
I could use CrossVersion.patch to publish it, but that would require me to republish a new version for every patch version of Scala, which seems like overkill since Scala 3 guarantees backwards and forwards compatibility on patch changes, which means there can’t be any changes to the reflect module that would require me to release a new version.
For a library like this, CrossVersion.minor seems to be what I’m really after. I think it would be worth adding. What do you think?
another possibility is to use semantic versioning that steps in line with scala minor version, and you could potentially add extra patches in older minors for bug fixes if you intend to continue supporting multiple minors
or manually naming the project foo-3.5 (aka foo-3.5_3)
Yeah, that’s not too bad. It does come with a few annoyances:
Either you drop semver, or you limit yourself to patch releases. Given that a scala LTS version lives at least two years, maybe longer, and given that hobby and research projects often choose next, I think you want to cater to both of those and for a young library, not releasing minor changes in more than 2 years is really long.
Of course, CrossVersion.minor is also semantically what a library like this wants. If you update your minor Scala version, SBT should automatically select the the new version of the library as well, since introspecting a new minor version with an old library will give the inspector blind spots.
Yeah, something like this is what I’m currently favoring.
Although I thought about naming it foo_3.5 and then telling the user to use % instead of %%. They need to change the version number themselves anyway currently and if CrossVersion.minor gets added to SBT someday, I can just switch to %% and CrossVersion.minor and the old releases should just-work™.
Also, this way, instead of releasing on lock-step with Scala 3 minor versions, I have way more freedom in how to version the library.
Couldn’t the version suffix be the minimal required / supported TASTy version instead of “_3”?
This would make all the CrossVersion.* settings superfluous I think. (You’d had a “TargetTastyVersion”, or something like that, instead).
Also it had the additional benefit that such a scheme would work even better with the use-case presented here. Because a minor Scala 3 version does not necessary increase the TASTy version, AFAIK. In that case needing a different version of some TASTy processing lib would be a waste, but the CrossVersion.minor approach would force such a version bump even if nothing changed regarding TASTy.
To be honest, all that counts for Scala’s “binary compatibility” is the TASTy version, and not some “arbitrary” release numbers (even there are rules how both need to interact). The TASTy version is the equivalent of the bytecode level on the JVM, and that’s the thing you target for bin compat. (Just that we need to care about both “binary compatibility levels” at the same time—of course in addition to source compatibility—instead doing the sane thing and not relying on the grotesque horrors of “binary” distribution ).
I don’t know exactly when the TASTy version gets bumped. Does every addition of a new type or a new flag to the public API of the scala/quoted/Quotes$reflectModule lead to a bump in the version number? If so, then I think targeting the TASTy version would work.
The policy is to increase the TASTy minor version when the compiler minor version increases - because it also protects against depending on new std-lib API changes (also the compiler minor only bumps when there is a new API/TASTy feature/source incompat)
the rationale, is that there is a compile-time error that prevents you from possibly depending on future API. So if std-lib adds a new method, then you will get an error if you try to compile against it using an earlier scala version