improvement-proposals icon indicating copy to clipboard operation
improvement-proposals copied to clipboard

SIP-61 - Unroll Default Arguments for Binary Compatibility

Open lihaoyi opened this issue 1 year ago • 11 comments

lihaoyi avatar Feb 15 '24 02:02 lihaoyi

CC @eed3si9n @alexarchambault @julienrf, who have worked on similar proposals/libraries/compiler-plugins in the past

lihaoyi avatar Feb 16 '24 14:02 lihaoyi

@alexarchambault please give it a try! Do note that the current published compiler plugin uses an older version of the proposal. You can take a look at the linked example PRs to see how to use it

lihaoyi avatar Feb 17 '24 01:02 lihaoyi

I have updated the writeup and prototype implementation with support for abstract method defs, with the same limitation that any downstream implementations must be final (i.e. no override alliowed). This opens up @unroll for usage in interfaces, which will definitely prove handy: interface methods have to evolve just as much as final methods do!

I am reasonably confident the treatment of abstract method defs is correct, but please help me take a look at the section Abstract Methods and help me double check things.

lihaoyi avatar Feb 19 '24 13:02 lihaoyi

Also CC @lefou and @lolgab as the folks who have been pushing for binary-compatibility and semantic versioning within the com.lihaoyi ecosystem; would be great if you guys could help give this proposal a read through and see if it makes sense

lihaoyi avatar Feb 19 '24 13:02 lihaoyi

Adding an abstract method to an open hierarchy is never a backward binary compatible change: it breaks existing subclasses. It's OK if the whole hierarchy is sealed.

sjrd avatar Feb 19 '24 13:02 sjrd

Adding an abstract method to an open hierarchy is never a backward binary compatible change: it breaks existing subclasses. It's OK if the whole hierarchy is sealed.

in this case, @unroll generates reverse forwarders such that no abstract methods are added or removed. MiMa passes, and my own ad-hoc classpath munging tests pass.

I don't know whether you've read through the updated proposal, but there's a whole section on the unrolling of abstract methods and why it allows addition of default parameters to be backwards binary compatible and semantically compatible. If there's something I missed please call it out for discussion

lihaoyi avatar Feb 19 '24 13:02 lihaoyi

I think having at least the option to mark the generated forwarder methods as deprecated is important. Although binary compatibility is the driving concern here, APIs are use by developers who need to understand and decide which method they should go for. Without any @deprecation notice, they may choose the wrong, resulting in unnecessarily limited compatibility. And I'm also having polyglot APIs, reflection acces and ScalaDoc in mind, where it matters, which explicit API is recent and what is deprecated; in contrast to pure Scala code, where the compile is most likely deciding which override to call.

And since @deprecated takes a since parameter which is IMHO important, we most likely need a since in @unroll too.

lefou avatar Feb 19 '24 14:02 lefou

@lrytz suggested that in Scala 2 we could generate the forwarders post pickler phase, which makes them invisible to downstream Scala compilation runs. And Scala 3 there is an Invisible annotation that does the same thing

I havent implemented these in the prototype yet, bit they sound like they would work

lihaoyi avatar Feb 19 '24 14:02 lihaoyi

I have updated the prototype implementation to use the post-pickler/invisible approach to hiding the generated forwarder methods, and updated the doc accordingly

lihaoyi avatar Feb 22 '24 04:02 lihaoyi

@alexarchambault I have published the latest version of @unroll, in accordance to this proposal. You can use it in Mill via

  def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg(ivy"com.lihaoyi::unroll-plugin:0.1.12")
  def ivyDeps = super.ivyDeps() ++ Agg(ivy"com.lihaoyi::unroll-annotation:0.1.12")

lihaoyi avatar Mar 21 '24 06:03 lihaoyi

@lrytz I have moved the Abstract Methods section out of the main proposal into the Alternatives section, as discussed during the meeting since we won't be implementing it as part of this proposal

lihaoyi avatar May 24 '24 14:05 lihaoyi

The proposal was unanimously "Accepted for implementation" in the May SIP meeting, given these latest changes:

  • @unroll is only supported on final methods; the "Abstract Methods" section is now under "Alternatives"
  • @unrollAll is also under "Alternatives", so not part of the accepted proposal

lrytz avatar Aug 16 '24 09:08 lrytz

@lihaoyi does the text in the merged file represent the current state approved spec?

bishabosha avatar Aug 21 '24 15:08 bishabosha

@bishabosha yes that's the current state of the approved spec. The Scala 3 compiler plugin in https://github.com/com-lihaoyi/unroll should mostly work, though we'd need to disable to abstract method support and replace it with error reporting for that and any non-final methods

lihaoyi avatar Aug 21 '24 23:08 lihaoyi

FYI for everyone, @bishabosha will be picking up the work integrating the current POC compiler plugin into the dotty mainline repo

lihaoyi avatar Aug 22 '24 00:08 lihaoyi