Skip to content

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

@lrytz

Description

@lrytz
Member

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.

Activity

added this to the 2.13.0-M5 milestone on May 25, 2018
self-assigned this
on May 25, 2018
retronym

retronym commented on May 29, 2018

@retronym
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

lrytz commented on May 31, 2018

@lrytz
MemberAuthor

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

retronym commented on Jun 1, 2018

@retronym
Member
modified the milestones: 2.13.0-M5, 2.13.1 on Aug 8, 2018
modified the milestones: 2.13.1, 2.13.2, bak, Backlog on Jul 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @retronym@adriaanm@lrytz

      Issue actions

        Fragile initialization of runtime reflection universe, forces a large graph · Issue #10903 · scala/bug