Heh, can you add “Milestone 4 - Add ‘inline’ to Scala 2”? That would be really great for Quill users. (just kidding of course! )
In all seriousness, this looks like a great plan! I didn’t expect Scala 3 compiled macros to ever be cross-portable to Scala 2 codebases so this definitely comes as a pleasant surprise to me, although I’m not exactly sure what to do with this capability yet. In Quill’s case specifically, Scala 3 Quill will no longer be relying on Whitebox macros that write AST trees into Java annotations; the annotation-passing mechanism will rely on Dotty’s ‘Inline’ construct. This means that all compile-time generated Scala3-Quill queries/quotes (i.e. everything… quote { in here! }
) will have to be assigned into inline def
s as opposed to val
s or var
s. Since Scala 2 does not have an inline
construct, using Scala3-Quill cross-ported into Scala 2 would only allow Runtime query generation, not compile-time. For some use-cases, this might be reasonable, for other use-cases it might not. I need to think about it further.
The alternative, of course, is to write a ScalaFix component that would re-write val
s that carry quotations into inline def
s and try to get a cross-build working that way. I don’t know the full consequences of doing it like that but perhaps Quill’s own testing code could be adapted to this pattern. However since, Scala-Quill3 has a different component-model this might not actually make sense (at least for a large subset of the tests).
I expect many similar issues will be encountered by authors of Macro-based libraries as they take the plunge into Scala 3 meta. Library authors who decide to go through the pain of porting their macro-based code into Scala 3 will want to be able to use the new capabilities of Scala 3 meta to give their users new features so that their users themsevles have an incentive to switch. That’s the only way that the entire process is worth it. The ‘inline’ construct is the foundation of most of these features.
Trying to look at things holistically, I think its about what combinations of tools to use and about what reasonable usage patterns can emerge. ScalaFix will be required for some parts of the problem, but it cannot be relied upon to refactor a massively large codebases. Cross-portability can try to solve the problem from the other end but Scala 3 macros might not sensibly be structured the same ways as their Scala 2 equivalents. That means a codebase may itself need to be wrangled into some sort of Scala 2 “compatibility mode”. Ultimately a combination of approaches will be necessary.
Thank you for your post @bishabosha, hopefully this will be the start of a larger conversation.