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

Fragile initialization of runtime reflection universe, forces a large graph #10903

Open
lrytz opened this issue May 25, 2018 · 3 comments
Open
Assignees
Milestone

Comments

@lrytz
Copy link
Member

lrytz commented May 25, 2018

Diagnosis of https://github.com/scala/scala/pull/6676/files#diff-04841eeda02f00638b4cda505dbeafbeR766

Definitions.init carefully forces core types in a specific order (e.g., first load the scala package, then create synthetic members such as Nothing). See this epic comment in JavaUniverse.init().

In reality ObjectClass.initialize already forces the scala package. Object has no parent class, so the ClassfileParser / FromJavaClassCompleter use definitions.AnyClass in this case, which is defined as enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT).

  • Forcing the scala package calls openPackageModule, which forces the package object.

  • The unpickler looks for annotations on members (@deprecated val Stream), which calls StreamSymbol.addAnnotation.

  • annotations has the following "interesting" code:

    if (!isCompilerUniverse && !isThreadsafe(purpose = AllOps)) initialize
    _annotations
    
  • So the compiler does not initialie the Stream class, while runtime reflection does

  • In the case of runtime reflection

    • The Stream class is unpickled
    • Since Cons/Empty are defined in the companion object, they are part of the pickle of Stream
    • The unpickler reads the @SVUID annotation on Empty and calls addAnnotation
    • This causes Empty extends Stream[Nothing] to be initialized, the unpickler tries to resolve scala.Nothing
    • But that fails: Nothing has not yet been enetered into the scala package. Look again at Definitions.init, we're still in ObjectClass.initialize. Nothing would be added only in symbolsNotPresentInBytecode.

Not sure where to break the cycle. Completing the scala package needs the synthetic scala.Nothing, but adding it requires the package to be completed. Suggestions welcome.

@retronym
Copy link
Member

Maybe the package loader should be responsible for adding the synthetics like Nothing to the scala package, rather than trying to do it externally.

@lrytz
Copy link
Member Author

lrytz commented May 31, 2018

Here's a prototype that works, but it's pretty un-pretty... https://github.com/scala/scala/compare/2.13.x...lrytz:t10903?expand=1

Need to be really careful not to force stuff.

@retronym
Copy link
Member

retronym commented Jun 1, 2018 via email

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

3 participants