diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-11-07 23:12:43 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-11-28 13:51:45 +1000 |
commit | 54d12f0581f6401c7693ccb0e3105868da19cec2 (patch) | |
tree | cb9eadf87e868312b1b233fede26b84c3e5504dd /src/reflect/scala/reflect/internal/pickling | |
parent | 028420cd80a2cf1127790fdd28088f6db575e8dd (diff) | |
download | scala-54d12f0581f6401c7693ccb0e3105868da19cec2.tar.gz scala-54d12f0581f6401c7693ccb0e3105868da19cec2.tar.bz2 scala-54d12f0581f6401c7693ccb0e3105868da19cec2.zip |
SI-8502 Improve resiliance to absent packages
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.
Two existing test cases have progressed, and the checkfiles are
accordingly updated.
Diffstat (limited to 'src/reflect/scala/reflect/internal/pickling')
-rw-r--r-- | src/reflect/scala/reflect/internal/pickling/UnPickler.scala | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index a35620a994..1fc7aebab0 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -211,7 +211,12 @@ abstract class UnPickler { def fromName(name: Name) = name.toTermName match { case nme.ROOT => loadingMirror.RootClass case nme.ROOTPKG => loadingMirror.RootPackage - case _ => adjust(owner.info.decl(name)) + case _ => + val decl = owner match { + case stub: StubSymbol => NoSymbol // SI-8502 Don't call .info and fail the stub + case _ => owner.info.decl(name) + } + adjust(decl) } def nestedObjectSymbol: Symbol = { // If the owner is overloaded (i.e. a method), it's not possible to select the @@ -389,13 +394,23 @@ abstract class UnPickler { case CLASSINFOtpe => ClassInfoType(parents, symScope(clazz), clazz) } + def readThisType(): Type = { + val sym = readSymbolRef() match { + case stub: StubSymbol if !stub.isClass => + // SI-8502 This allows us to create a stub for a unpickled reference to `missingPackage.Foo`. + stub.owner.newStubSymbol(stub.name.toTypeName, stub.missingMessage) + case sym => sym + } + ThisType(sym) + } + // We're stuck with the order types are pickled in, but with judicious use // of named parameters we can recapture a declarative flavor in a few cases. // But it's still a rat's nest of adhockery. (tag: @switch) match { case NOtpe => NoType case NOPREFIXtpe => NoPrefix - case THIStpe => ThisType(readSymbolRef()) + case THIStpe => readThisType() case SINGLEtpe => SingleType(readTypeRef(), readSymbolRef().filter(_.isStable)) // SI-7596 account for overloading case SUPERtpe => SuperType(readTypeRef(), readTypeRef()) case CONSTANTtpe => ConstantType(readConstantRef()) |