Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(scala3): WIP working on scala 3 cross compilation. #390. #461

Merged
merged 29 commits into from
Mar 28, 2022

Conversation

brbrown25
Copy link
Contributor

@brbrown25 brbrown25 commented Nov 19, 2021

  • scala 3 rewrite compiler specific code

@brbrown25 brbrown25 marked this pull request as draft November 19, 2021 15:51
@ahjohannessen
Copy link
Contributor

@brbrown25 What is the status on this? :)

@brbrown25
Copy link
Contributor Author

@brbrown25 What is the status on this? :)

I had something come up at work and didn't get to make progress, but next week I have time carved out and will push some updates :)

@ahjohannessen
Copy link
Contributor

👍

@brbrown25 brbrown25 force-pushed the ISSUE-390 branch 2 times, most recently from d6b6adb to 8b5fe47 Compare December 30, 2021 17:05
@brbrown25
Copy link
Contributor Author

@ahjohannessen I've gotten about as far as I can with this. My understanding of macros is limited so I tried to stumble through. I will say that the only thing remaining is to fix up compiler/src/main/scala-3/play/twirl/compiler/TwirlCompiler.scala otherwise I've validated that the others cross compile fine. The only thing we can't make cross compiled is the plugin as it looks like that stops support at 2.12. Sorry I couldn't get it any further along.

@ahjohannessen
Copy link
Contributor

ahjohannessen commented Dec 30, 2021

@brbrown25 sbt build definitions are on Scala 2.12, so that is expected. I suppose what is missing is some kind soul that knows Scala 3 macros to step up :)

Edit: I meant sbt plugins are only 2.12.

@brbrown25
Copy link
Contributor Author

@brbrown25 sbt build definitions are on Scala 2.12, so that is expected. I suppose what is missing is some kind soul that knows Scala 3 macros to step up :)

Yeah I got it about as far as I could understand, it's definitely new and exciting territory!

@ahjohannessen
Copy link
Contributor

@brbrown25 Which macros need porting?

@brbrown25
Copy link
Contributor Author

@brbrown25 Which macros need porting?

the following are the things of note. The big one is figuring out the correct imports/way of handling ValDef and Tree. But the things requiring fixing should be isolated to that file and the TemplateAsFunctionCompiler object



(the updating the bootclasspath)
def treeFrom(file: SourceFile): Tree = {

@ahjohannessen
Copy link
Contributor

@brbrown25 Briefly
Scanned through the code, seems there is no
macro usage as far as I can tell. Is it more about interacting with the new compiler API that is the hurdle?

@brbrown25
Copy link
Contributor Author

@brbrown25 Briefly Scanned through the code, seems there is no macro usage as far as I can tell. Is it more about interacting with the new compiler API that is the hurdle?

Yeah the compiler Api is the hurdle, although tts actually possibly that macros could be used in place of the compiler Api, for this case, but I'm not 100% on that.

build.sbt Show resolved Hide resolved
@brbrown25 brbrown25 force-pushed the ISSUE-390 branch 3 times, most recently from 64097c4 to 7030de6 Compare January 4, 2022 13:32
@ahjohannessen
Copy link
Contributor

@brbrown25 This seems interesting tototoshi@6bcb772

@brbrown25
Copy link
Contributor Author

@brbrown25 This seems interesting tototoshi@6bcb772

@ahjohannessen I can pull in those changes and update this probably late this evening for first thing tomorrow!

@tototoshi
Copy link
Member

My branch is here. https://github.com/tototoshi/twirl/tree/scalameta

I think it might be easier to share the source code between scala2 and scala3 using scalameta than using presentation compiler. (I don't know if twirl can depend on scalameta 🤔 ).

The main code already can be built in scala3, but the test code not yet. It has tests that confirm the generated codes can be really compiled, so still requires dotty.

@brbrown25
Copy link
Contributor Author

My branch is here. https://github.com/tototoshi/twirl/tree/scalameta

I think it might be easier to share the source code between scala2 and scala3 using scalameta than using presentation compiler. (I don't know if twirl can depend on scalameta 🤔 ).

I'm gonna play around with that and I agree if we came remove the presentation compiler piece it should make life a lot easier.

@brbrown25
Copy link
Contributor Author

@tototoshi I merged your work into mine and then tweaked mine to accommodate your scalameta changes, indeed it gets compiler to run the compile stage happily enough. The only piece that remains is updating the CompilerSpec so that the tests pass under all versions. I'll try and look at that today, but feel free to hack around with what's in this, I think we're getting pretty close!

@tototoshi
Copy link
Member

I have implemented a dotty-based test helper in my working branch to support Scala3. So now it can be built with Scala3, including the tests.
https://github.com/tototoshi/twirl/tree/scalameta

And I found another problem.

In Scala2, an if expression without else returns Any or AnyVal, but in Scala3, it seems to return Unit.
It makes Scala3 display nothing when using twirl @if without else.

// Scala 2.13
scala> val a = if (true) 1
val a: AnyVal = 1

scala> val a = if (true) "a"
val a: Any = a
// Scala 3
scala> val a = if (true) 1
1 warning found
-- [E129] Potential Issue Warning: ---------------------------------------------
1 |val a = if (true) 1
  |                  ^
  |A pure expression does nothing in statement position; you may be omitting necessary parentheses

longer explanation available when compiling with `-explain`

scala> println(a)
()

I modified the TwirlParser to interpret the if without else as Twirl syntax instead of Scala code.
I think the implementation needs some refactoring, but It passes tests at least.

Copy link
Member

@mkurz mkurz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for you work!
Some minor things need to be addressed.
Also I think you actually didn't run the test on Travis with the correct Scala version... So let's see how that turns out after setting the correct version.

Also, the changes in TwirlParser look ok to me, I know this needed change because of the if problem you described, however I hope this is not breaking apps.

Please update the pull request, I may review a second time and after merging, we can release 1.6.0-M2 so people can start testing.
Thanks again!

build.sbt Outdated Show resolved Hide resolved
build.sbt Outdated Show resolved Hide resolved
.travis.yml Outdated Show resolved Hide resolved
.travis.yml Outdated Show resolved Hide resolved
@brbrown25 brbrown25 requested a review from mkurz March 10, 2022 14:20
@mkurz
Copy link
Member

mkurz commented Mar 11, 2022

I did some local testing:

$ sbt
sbt:twirl> ++3.1.1
sbt:twirl> test
...
-- [E006] Not Found Error: /home/mkurz/work/github-play-repos/twirl/compiler/target/test/twirl-parser/generated-templates/html/error.template.scala:19:63 
19 |Seq[Any](format.raw/*2.1*/("""<h1>Hello """),_display_(/*2.12*/world),format.raw/*2.17*/("""</h1>
   |                                                               ^^^^^
   |                                                        Not found: world

...

here is a screenshot so you see this is highlighted in red:
image

This from

"fail compilation for error.scala.html" in {
val helper = newCompilerHelper
the[CompilationError] thrownBy helper.compile[(() => Html)]("error.scala.html", "html.error") must have(
Symbol("line")(2),
Symbol("column")(12)
)
}

However, it is not a real error, the test passes and the CompilationError object will correctly be thrown. I guess this is just the output of the Scala 3 compiler twirl executes... However the problem I have with that is that these log entries may confuse people... In Scala 2.12/2.13 these entries will not be displayed (because the Scala 2 compiler is used which obviously acts different).
Is it possible to suppress this log?

@brbrown25
Copy link
Contributor Author

I'm away from computer for a few days for family vacation but can look into n it when I return.

@tototoshi
Copy link
Member

I added a commit to suppress compile errors log.
@brbrown25 Have a good vacation 😄

@mkurz
Copy link
Member

mkurz commented Mar 11, 2022

@tototoshi I looked at your last commit, however you now suppress logging of compile errors only for tests? Or am I wrong? My idea was to always suppress that errors, not just for the CI tests... It would be also confusing in real apps to see that errors. WDYT?

@brbrown25
Copy link
Contributor Author

@tototoshi thank you!

@tototoshi
Copy link
Member

@mkurz
My change is only for tests. In real apps, the compilation of the scala files generated by twirl is the task of sbt-twirl.
And sbt-twirl does not support cross-build against scala3 yet (because it is sbt-plugin running only on scala 2.12).
I think the problem you are thinking about will appear in the future when sbt is running on scala 3. But as for now, I think the current state is enough.

@tototoshi
Copy link
Member

Umm... My understanding may be wrong. sbt-plugin runs on scala2.12 but the compilation of templates should be run on scala3.
OK. I will check it later.

@tototoshi
Copy link
Member

Now I understand the problem.
It seems that the sourcePositionMappers setting provided by sbt-twirl doesn't work with Scala3. I didn't add changes to sbt-plugin, and the sources generated by twirl has no difference between Scala2 and Scala3.
I doubt this problem comes with sbt and dotty. I will investigate them next.

@tototoshi
Copy link
Member

I found the cause.

https://github.com/lampepfl/dotty/blob/d2ebd75a2e63e3dd885e7bad94472931d0bae296/sbt-bridge/src/dotty/tools/xsbt/DelegatingReporter.java#L47

When Scala3 is compiled using sbt, compilation errors are reported by this DelegatingReporter. DelegatingReporter delegates the log output process to sbt's ManagedLoggedReporter. The problem seems to be that the error information passed to ManagedLoggedReporter includes messages generated by Dotty as rendered parameter of Problem.

If the rendered parameter is included in the error information, sbt will display the contents of the rendered parameter, and information other than the rendered parameter is ignored. So the error information in the Twirl template translated by sourcePositionMappers in LoggedReporter will not be displayed.

https://github.com/sbt/sbt/blob/fedf6af60d86ed39ae9c94161f13a79ffc4494e8/internal/util-interface/src/main/java/xsbti/Problem.java#L21-L28
https://github.com/sbt/zinc/blob/f6d36ff81aab6063a8ed5dd06c51ea6b9fef16f8/internal/zinc-compile-core/src/main/scala/sbt/internal/inc/ProblemStringFormats.scala#L27-L28

If I modify the DelegatingReporter so that the rendered parameter is not passed to sbt, it is possible to display the same error message as when compiling with Scala2. However, the message stored in the rendered parameter is from the Dotty compiler and contains more detailed error messages, so I feel a bit uncomfortable making it completely invisible.

I think I have nothing that I can do In this Twirl repository, and ideally, either or both sbt and Dotty's sbt integration need to be improved.

@tototoshi
Copy link
Member

scala/scala3#14691

@brbrown25
Copy link
Contributor Author

@tototoshi, @mkurz I just realized I messed up and didn't update the travis.yml so I've pushed that fix and we should get a clean travis pass on 3.1.1 now.

@mkurz
Copy link
Member

mkurz commented Mar 21, 2022

Travis not working, closeing/reopening to trigger it...

@mkurz mkurz closed this Mar 21, 2022
@mkurz mkurz reopened this Mar 21, 2022
@brbrown25
Copy link
Contributor Author

@mkurz since we got green builds in Travis do you think we might be ready to merge this soon?

Copy link
Member

@mkurz mkurz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK lets merge. Like said I did some local testing, also tests on CI pass so it looks promising. In case problems occur when can always fix them in upcoming pr/commits.
@tototoshi I saw sbt/zinc#1074 (comment), if you come up with a fix let us know.

I am too tired now, but I can release 1.6.0-M2 this week so people can play around with it, also to upgrade in other projects like Play to see if we trigger some other bugs.

@mkurz mkurz merged commit addebd0 into playframework:main Mar 28, 2022
@mkurz
Copy link
Member

mkurz commented Mar 28, 2022

Opened #498 to keep track of the Scala 3/sourcePositionMapper problem

@ihostage ihostage added this to the 1.6.0 milestone Apr 14, 2022
@mkurz
Copy link
Member

mkurz commented Nov 13, 2023

This causes

If someone has time to look into that, I would appreciate it, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants