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

Async code access to a variable in App fails in Dotty #16149

Open
mkotsur opened this issue Oct 7, 2022 · 6 comments
Open

Async code access to a variable in App fails in Dotty #16149

mkotsur opened this issue Oct 7, 2022 · 6 comments

Comments

@mkotsur
Copy link

mkotsur commented Oct 7, 2022

Compiler version

3.2.0

Minimized code

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

object MapTest extends App {
  import concurrent.ExecutionContext.Implicits.global

  val test = "123"

  val dataF = Future { List("111", "222", "333", test) }

  Await.ready(dataF, 1.second)
}

Output

Exception in thread "main" java.lang.ExceptionInInitializerError
	at MapTest.main(MapTest.scala)
Caused by: java.util.concurrent.TimeoutException: Future timed out after [1 second]
	at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:248)
	at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:255)
	at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:104)
	at scala.concurrent.Await$.$anonfun$ready$1(package.scala:174)
	at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:62)
	at scala.concurrent.Await$.ready(package.scala:124)
	at MapTest$.<clinit>(MapTest.scala:13)
	... 1 more
java.lang.NoClassDefFoundError: Could not initialize class MapTest$

Expectation

I'm aware of the intricacies of DelayedInit and App. However, since this works in Scala 2.13, I would expect this to also work in Scala 3 because the doc hasn't change: doc dotty, doc 2.13.3.

Moreover, looking at this statement:

It should be noted that this trait is implemented using the DelayedInit functionality, which means that fields of the object will not have been initialized before the main method has been executed.

it's not clear why wrapping code into a Future makes any difference. Isn't access to test on line 3 happening before the method has been executed? 🤔

object PrintTest extends App {
  val test = "123"
  println(test)
}
@mkotsur mkotsur added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 7, 2022
@SethTisue
Copy link
Member

maybe scala/scala#10070 hasn't propagated to Scala 3 yet? it was included in Scala 2.13.9: https://www.scala-lang.org/api/2.13.9/scala/App.html (it's a bit peculiar that you linked to the 2.13.3 doc above; that's a quite old version)

@som-snytt
Copy link
Contributor

2.13.3 is when -Xasync arrived. It was the second pandemic release. The pandemic is already quite old.

@som-snytt
Copy link
Contributor

There are many Scala 2 tickets about deadlocking a class initializer (object). From pandemic era:

scala/bug#12278

There is a comment on that ticket about differences in dotty.

@odersky odersky added area:documentation and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 9, 2022
@odersky
Copy link
Contributor

odersky commented Oct 9, 2022

Yes, I think the dotty documentation of App is not up to date. I wonder where it came from? I assumed that it just copied the 2.13 docs?

@mkotsur
Copy link
Author

mkotsur commented Oct 10, 2022

Two small notes and two suggestions...

  1. @SethTisue no real reason why I linked 2.13.3, not the latest one. Apologies if this confused you.

  2. One more thing I noted: 3.1.2 has warning suppression @nowarn("cat=deprecation&origin=scala\\.DelayedInit") on the App trait, while 3.1.3 doesn't. I don't know if this is relevant.

While it would be very helpful if scala/scala#10070 changes were present in dotty's docs, I don't think it will necessarily prevent people from wasting time on writing and debugging the kind of code that I demonstrated. Even if you carefully read the whole thing (which not many people do tbh), you may still think that it's OK to use App for a quick sketch, and the only real risk is that it will be deprecated in the Future. Not that it will misbehave. Especially since the DelayedInit feature was dropped – it was said to be the cause of the funky initialization behaviour.

Is there a reason not to make the trait deprecated already?
Can we emphasize the recommendation to use @main by pulling it to the top of the text?

@SethTisue
Copy link
Member

Yes, I think the dotty documentation of App is not up to date. I wonder where it came from? I assumed that it just copied the 2.13 docs?

That should be resolved in 3.2.1 by #16074

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

No branches or pull requests

4 participants