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

SI-8502 Improve resiliance to absent packages #4111

Closed
wants to merge 1 commit into from

Conversation

retronym
Copy link
Member

@retronym retronym commented Nov 7, 2014

When unpickling a class, we create stub symbols for references
to classes absent from the current classpath. If these references
only appear in method signatures that aren't called, we can
proceed with compilation. This is in line with javac.

We're getting better at this, but there are still some gaps.
This bug is about the behaviour when a package is completely
missing, rather than just a single class within that package.

To make this work we have to add two special cases to the unpickler:

  • When unpickling a ThisType, convert a StubTermSymbol into
    a StubTypeSymbol. We hit this when unpickling
    ThisType(missingPackage).
  • When unpickling a reference to <owner>.name where <owner>
    is a stub symbol, don't call info on that owner, but rather
    allow the enclosing code in readSymbol fall through to
    create a stub for the member.

The test case was distilled from an a problem that a Spray user
encountered when Akka was missing from the classpath.

Review by @gkossakowski

When unpickling a class, we create stub symbols for references
to classes absent from the current classpath. If these references
only appear in method signatures that aren't called, we can
proceed with compilation. This is in line with javac.

We're getting better at this, but there are still some gaps.
This bug is about the behaviour when a package is completely
missing, rather than just a single class within that package.

To make this work we have to add two special cases to the unpickler:

  - When unpickling a `ThisType`, convert a `StubTermSymbol` into
    a `StubTypeSymbol`. We hit this when unpickling
    `ThisType(missingPackage)`.
  - When unpickling a reference to `<owner>.name` where `<owner>`
    is a stub symbol, don't call info on that owner, but rather
    allow the enclosing code in `readSymbol` fall through to
    create a stub for the member.

The test case was distilled from an a problem that a Spray user
encountered when Akka was missing from the classpath.
@scala-jenkins scala-jenkins added this to the 2.11.5 milestone Nov 7, 2014
@retronym
Copy link
Member Author

retronym commented Nov 7, 2014

Here is how to reproduce the failure from the command line:

% tail sandbox/{b,c}.scala; scalac-hash v2.11.4 sandbox/{b,c}.scala && rm vanishing/Vanishing.class && rmdir vanishing && scalac-hash v2.11.4 sandbox/c.scala
==> sandbox/b.scala <==
object U {
  def foo(log: vanishing.Vanishing) = ()
}

package vanishing {
  class Vanishing
}

==> sandbox/c.scala <==
trait Test {
  U
}
error: scala.reflect.internal.Types$TypeError: missing or invalid dependency detected while loading class file 'U.class'.
Could not access term vanishing in package <root>,
because it (or its dependencies) are missing. Check your build definition for
missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.)
A full rebuild may help if 'U.class' was compiled against an incompatible version of <root>.
    at scala.tools.nsc.typechecker.Contexts$ThrowingReporter.handleError(Contexts.scala:1387)
    at scala.tools.nsc.typechecker.Contexts$ContextReporter.info0(Contexts.scala:1283)
    at scala.tools.nsc.typechecker.Contexts$ContextReporter.info0(Contexts.scala:1237)
    at scala.reflect.internal.Reporter.error(Reporting.scala:82)

@retronym retronym closed this Nov 7, 2014
lrytz added a commit to lrytz/scala that referenced this pull request Jul 20, 2015
scala#4111 creates a stub type symbol
for missing packages, deferring (or avoiding) a crash if a package
is missing.

The symbol created was a ClassSymbol, which could lead to an assertion
failure in flattten:

    case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) =>
      assert(args.isEmpty && sym.enclosingTopLevelClass != NoSymbol, sym.ownerChain)

`pre` is the stub ClassSymbol, so `isFlattenablePrefix` is true (but
it should be false). The assertion then fails because the enclosing
class of a top-level class defined in a missing package is NoSymbol.

This failed only with GenBCode, which traverses more of the symbol
graph while building ClassBTypes: it looks collects the nested classes
of `Outer` into a `NestedInfo`.
lrytz added a commit to lrytz/scala that referenced this pull request Jul 20, 2015
scala#4111 creates a stub type symbol
for missing packages, deferring (or avoiding) a crash if a package
is missing.

The symbol created was a ClassSymbol, which could lead to an assertion
failure in flattten:

    case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) =>
      assert(args.isEmpty && sym.enclosingTopLevelClass != NoSymbol, sym.ownerChain)

`pre` is the stub ClassSymbol, so `isFlattenablePrefix` is true (but
it should be false). The assertion then fails because the enclosing
class of a top-level class defined in a missing package is NoSymbol.

This failed only with GenBCode, which traverses more of the symbol
graph while building ClassBTypes: it looks collects the nested classes
of `Outer` into a `NestedInfo`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants