summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Depth.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala17
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala21
-rw-r--r--src/reflect/scala/reflect/internal/tpe/FindMembers.scala14
-rw-r--r--src/reflect/scala/reflect/internal/transform/RefChecks.scala0
-rw-r--r--src/reflect/scala/reflect/io/ZipArchive.scala76
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala2
7 files changed, 103 insertions, 29 deletions
diff --git a/src/reflect/scala/reflect/internal/Depth.scala b/src/reflect/scala/reflect/internal/Depth.scala
index a330e0accb..5e7202f8bf 100644
--- a/src/reflect/scala/reflect/internal/Depth.scala
+++ b/src/reflect/scala/reflect/internal/Depth.scala
@@ -5,7 +5,7 @@ package internal
import Depth._
final class Depth private (val depth: Int) extends AnyVal with Ordered[Depth] {
- def max(that: Depth): Depth = if (this < that) that else this
+ def max(that: Depth): Depth = if (this.depth < that.depth) that else this
def decr(n: Int): Depth = if (isAnyDepth) this else Depth(depth - n)
def incr(n: Int): Depth = if (isAnyDepth) this else Depth(depth + n)
def decr: Depth = decr(1)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 9d71136fc5..854849d27c 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -193,6 +193,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private[reflect] case class SymbolKind(accurate: String, sanitized: String, abbreviation: String)
+ protected def newStubSymbol(owner: Symbol,
+ name: Name,
+ missingMessage: String): Symbol = {
+ name match {
+ case n: TypeName => new StubClassSymbol(owner, n, missingMessage)
+ case _ => new StubTermSymbol(owner, name.toTermName, missingMessage)
+ }
+ }
+
/** The class for all symbols */
abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name)
extends SymbolContextApiImpl
@@ -504,9 +513,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* failure to the point when that name is used for something, which is
* often to the point of never.
*/
- def newStubSymbol(name: Name, missingMessage: String, isPackage: Boolean = false): Symbol = name match {
- case n: TypeName => new StubClassSymbol(this, n, missingMessage)
- case _ => new StubTermSymbol(this, name.toTermName, missingMessage)
+ def newStubSymbol(name: Name, missingMessage: String): Symbol = {
+ // Invoke the overriden `newStubSymbol` in Global that gives us access to typer
+ Symbols.this.newStubSymbol(this, name, missingMessage)
}
/** Given a field, construct a term symbol that represents the source construct that gave rise the field */
@@ -3427,7 +3436,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private def fail[T](alt: T): T = {
// Avoid issuing lots of redundant errors
if (!hasFlag(IS_ERROR)) {
- globalError(missingMessage)
+ globalError(pos, missingMessage)
if (settings.debug.value)
(new Throwable).printStackTrace
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index b4152c9b8c..16fbab7103 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -246,14 +246,15 @@ abstract class UnPickler {
adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse {
// (4) Create a stub symbol to defer hard failure a little longer.
val advice = moduleAdvice(s"${owner.fullName}.$name")
+ val lazyCompletingSymbol = completingStack.headOption.getOrElse(NoSymbol)
val missingMessage =
- s"""|missing or invalid dependency detected while loading class file '$filename'.
- |Could not access ${name.longString} in ${owner.kindString} ${owner.fullName},
- |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.)
+ s"""|Symbol '${name.nameKind} ${owner.fullName}.$name' is missing from the classpath.
+ |This symbol is required by '${lazyCompletingSymbol.kindString} ${lazyCompletingSymbol.fullName}'.
+ |Make sure that ${name.longString} is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
|A full rebuild may help if '$filename' was compiled against an incompatible version of ${owner.fullName}.$advice""".stripMargin
val stubName = if (tag == EXTref) name else name.toTypeName
- owner.newStubSymbol(stubName, missingMessage)
+ // The position of the error message is set by `newStubSymbol`
+ NoSymbol.newStubSymbol(stubName, missingMessage)
}
}
}
@@ -696,11 +697,18 @@ abstract class UnPickler {
new TypeError(e.msg)
}
+ /** Keep track of the symbols pending to be initialized.
+ *
+ * Useful for reporting on stub errors and cyclic errors.
+ */
+ private var completingStack = List.empty[Symbol]
+
/** A lazy type which when completed returns type at index `i`. */
private class LazyTypeRef(i: Int) extends LazyType with FlagAgnosticCompleter {
private val definedAtRunId = currentRunId
private val p = phase
protected def completeInternal(sym: Symbol) : Unit = try {
+ completingStack = sym :: completingStack
val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType`
// This is a temporary fix allowing to read classes generated by an older, buggy pickler.
@@ -723,7 +731,10 @@ abstract class UnPickler {
}
catch {
case e: MissingRequirementError => throw toTypeError(e)
+ } finally {
+ completingStack = completingStack.tail
}
+
override def complete(sym: Symbol) : Unit = {
completeInternal(sym)
if (!isCompilerUniverse) markAllCompleted(sym)
diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
index 6ba48cb44d..510d76793e 100644
--- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
@@ -285,4 +285,18 @@ trait FindMembers {
initBaseClasses.head.newOverloaded(tpe, members)
}
}
+
+ private[scala] final class HasMember(tpe: Type, name: Name, excludedFlags: Long, requiredFlags: Long) extends FindMemberBase[Boolean](tpe, name, excludedFlags, requiredFlags) {
+ private[this] var _result = false
+ override protected def result: Boolean = _result
+
+ protected def shortCircuit(sym: Symbol): Boolean = {
+ _result = true
+ true // prevents call to addMemberIfNew
+ }
+
+ // Not used
+ protected def addMemberIfNew(sym: Symbol): Unit = {}
+ }
+
}
diff --git a/src/reflect/scala/reflect/internal/transform/RefChecks.scala b/src/reflect/scala/reflect/internal/transform/RefChecks.scala
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/reflect/scala/reflect/internal/transform/RefChecks.scala
+++ /dev/null
diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala
index 262ab22ce9..f4e1633af4 100644
--- a/src/reflect/scala/reflect/io/ZipArchive.scala
+++ b/src/reflect/scala/reflect/io/ZipArchive.scala
@@ -27,6 +27,8 @@ import scala.annotation.tailrec
* ''Note: This library is considered experimental and should not be used unless you know what you are doing.''
*/
object ZipArchive {
+ private[io] val closeZipFile = sys.props.get("scala.classpath.closeZip").map(_.toBoolean).getOrElse(false)
+
/**
* @param file a File
* @return A ZipArchive if `file` is a readable zip file, otherwise null.
@@ -120,31 +122,69 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq
}
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
final class FileZipArchive(file: JFile) extends ZipArchive(file) {
+ private[this] def openZipFile(): ZipFile = try {
+ new ZipFile(file)
+ } catch {
+ case ioe: IOException => throw new IOException("Error accessing " + file.getPath, ioe)
+ }
+
+ private[this] class LazyEntry(
+ name: String,
+ time: Long,
+ size: Int
+ ) extends Entry(name) {
+ override def lastModified: Long = time // could be stale
+ override def input: InputStream = {
+ val zipFile = openZipFile()
+ val entry = zipFile.getEntry(name)
+ val delegate = zipFile.getInputStream(entry)
+ new FilterInputStream(delegate) {
+ override def close(): Unit = { zipFile.close() }
+ }
+ }
+ override def sizeOption: Option[Int] = Some(size) // could be stale
+ }
+
+ // keeps a file handle open to ZipFile, which forbids file mutation
+ // on Windows, and leaks memory on all OS (typically by stopping
+ // classloaders from being garbage collected). But is slightly
+ // faster than LazyEntry.
+ private[this] class LeakyEntry(
+ zipFile: ZipFile,
+ zipEntry: ZipEntry
+ ) extends Entry(zipEntry.getName) {
+ override def lastModified: Long = zipEntry.getTime
+ override def input: InputStream = zipFile.getInputStream(zipEntry)
+ override def sizeOption: Option[Int] = Some(zipEntry.getSize.toInt)
+ }
+
lazy val (root, allDirs) = {
val root = new DirEntry("/")
val dirs = mutable.HashMap[String, DirEntry]("/" -> root)
- val zipFile = try {
- new ZipFile(file)
- } catch {
- case ioe: IOException => throw new IOException("Error accessing " + file.getPath, ioe)
- }
-
+ val zipFile = openZipFile()
val enum = zipFile.entries()
- while (enum.hasMoreElements) {
- val zipEntry = enum.nextElement
- val dir = getDir(dirs, zipEntry)
- if (zipEntry.isDirectory) dir
- else {
- class FileEntry() extends Entry(zipEntry.getName) {
- override def getArchive = zipFile
- override def lastModified = zipEntry.getTime()
- override def input = getArchive getInputStream zipEntry
- override def sizeOption = Some(zipEntry.getSize().toInt)
+ try {
+ while (enum.hasMoreElements) {
+ val zipEntry = enum.nextElement
+ val dir = getDir(dirs, zipEntry)
+ if (zipEntry.isDirectory) dir
+ else {
+ val f =
+ if (ZipArchive.closeZipFile)
+ new LazyEntry(
+ zipEntry.getName(),
+ zipEntry.getTime(),
+ zipEntry.getSize().toInt
+ )
+ else
+ new LeakyEntry(zipFile, zipEntry)
+
+ dir.entries(f.name) = f
}
- val f = new FileEntry()
- dir.entries(f.name) = f
}
+ } finally {
+ if (ZipArchive.closeZipFile) zipFile.close()
}
(root, dirs)
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 7aa3b113dd..b455a08036 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -460,8 +460,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.DoubleTpe
definitions.BooleanTpe
definitions.ScalaNumericValueClasses
- definitions.ScalaValueClasses
definitions.ScalaValueClassesNoUnit
+ definitions.ScalaValueClasses
uncurry.VarargsSymbolAttachment
uncurry.DesugaredParameterType