scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.84k stars 1.05k forks source link

Scala 3.3.1: Concrete method inside `trait` marked (incorrectly?) as `ACC_BRIDGE` and `ACC_SYNTHETIC` #19270

Open mkurz opened 10 months ago

mkurz commented 10 months ago

Compiler version

3.3.1

Reproducer

(Sorry I don't have time to come up with a minimized code example)

git clone git@github.com:mkurz/play-samples.git
cd play-samples/play-scala-hello-world-tutorial
git checkout issue-12272
sbt run

# In another terminal (or use a browser)
curl localhost:9000

You will see the Play app fails with an exception. However the exact same application works just fine with Scala 2.13.12 (++2.x ; run).

Description why the problem occurs: Our controller class extends from the InjectedController trait (line):

class HomeController @Inject()() extends InjectedController {

The InjectedController trait defines a concrete method setControllerComponents which should get components injected by Guice (line)

  @Inject
  def setControllerComponents(components: ControllerComponents): Unit = {
    _components = components
  }

Problem: In Scala 2 Guice does inject components and calls the method, in Scala 3 it does not.

When decompiling HomeController.class (using javap -v) the method signature for setControllerComponents is different for Scala 2.13 and Scala 3.

Scala 2.13:

  public void setControllerComponents(play.api.mvc.ControllerComponents);
    descriptor: (Lplay/api/mvc/ControllerComponents;)V
    flags: (0x0001) ACC_PUBLIC

Scala 3:

  public void setControllerComponents(play.api.mvc.ControllerComponents);
    descriptor: (Lplay/api/mvc/ControllerComponents;)V
    flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC

So you see Scala 3 marks the method as synthetic bridge method (ACC_BRIDGE and ACC_SYNTHETIC).

Guice however ignores such methods: https://github.com/google/guice/blob/f095cad8aa7b59abafacc4d4461ddfc77be83667/core/src/com/google/inject/spi/InjectionPoint.java#L819-L841

The question I have is: Why is that concrete method marked as ACC_BRIDGE and ACC_SYNTHETIC in Scala 3? Is that a bug? If not, how can I make our code work? Are there any docs or notes on that behaviour?

Thanks!

Originally posted by @ThomasGrt in https://github.com/playframework/playframework/issues/12272

mkurz commented 10 months ago

If that is a bug in Scala, is there a chance a fix still makes it into 3.3.2-RC1, as I see there is

?

dwijnand commented 9 months ago

Why is that concrete method marked as ACC_BRIDGE and ACC_SYNTHETIC in Scala 3?

setControllerComponents being a trait method that sets instance state, it needs special handling to compile to classfiles. But hopefully we can make this use case work.

If that is a bug in Scala, is there a chance a fix still makes it into 3.3.2-RC1

I don't we have someone to work on this in the next 2 days. It's not high impacting nor a regression within 3.3.x.

987Nabil commented 7 months ago

@dwijnand Is this still on someones list?

gaeljw commented 1 week ago

Any update on this issue? While not critical AFAIK, it's still something that many users hit with Play Framework when migrating from Scala 2.13 to 3.x. Play being one of the main Scala frameworks I believe.