summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala24
-rw-r--r--src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala1
-rw-r--r--test/files/pos/t9086.scala8
-rw-r--r--test/files/run/t6502.check8
-rw-r--r--test/files/run/t6502.scala70
6 files changed, 77 insertions, 40 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9773028b76..6e5f61db1a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1536,7 +1536,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1)
val clazz = context.owner
assert(clazz != NoSymbol, templ)
- val dummy = context.outer.owner.newLocalDummy(templ.pos)
+ // SI-9086 The position of this symbol is material: implicit search will avoid triggering
+ // cyclic errors in an implicit search in argument to the super constructor call on
+ // account of the "ignore symbols without complete info that succeed the implicit search"
+ // in this source file. See `ImplicitSearch#isValid` and `ImplicitInfo#isCyclicOrErroneous`.
+ val dummy = context.outer.owner.newLocalDummy(context.owner.pos)
val cscope = context.outer.makeNewScope(ctor, dummy)
if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file
val cbody2 = { // called both during completion AND typing.
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 4fd5768b79..4d71e0e09e 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -12,6 +12,7 @@ import scala.annotation.tailrec
import Predef.{ println => _, _ }
import interpreter.session._
import StdReplTags._
+import scala.tools.asm.ClassReader
import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName }
import scala.tools.nsc.util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream }
import scala.reflect.classTag
@@ -633,28 +634,29 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* the interpreter and replays all interpreter expressions.
*/
def require(arg: String): Unit = {
- class InfoClassLoader extends java.lang.ClassLoader {
- def classOf(arr: Array[Byte]): Class[_] =
- super.defineClass(null, arr, 0, arr.length)
- }
-
val f = File(arg).normalize
- if (f.isDirectory) {
- echo("Adding directories to the classpath is not supported. Add a jar instead.")
+ val jarFile = AbstractFile.getDirectory(new java.io.File(arg))
+ if (jarFile == null) {
+ echo(s"Cannot load '$arg'")
return
}
- val jarFile = AbstractFile.getDirectory(new java.io.File(arg))
-
def flatten(f: AbstractFile): Iterator[AbstractFile] =
if (f.isClassContainer) f.iterator.flatMap(flatten)
else Iterator(f)
val entries = flatten(jarFile)
- val cloader = new InfoClassLoader
- def classNameOf(classFile: AbstractFile): String = cloader.classOf(classFile.toByteArray).getName
+ def classNameOf(classFile: AbstractFile): String = {
+ val input = classFile.input
+ try {
+ val reader = new ClassReader(input)
+ reader.getClassName.replace('/', '.')
+ } finally {
+ input.close()
+ }
+ }
def alreadyDefined(clsName: String) = intp.classLoader.tryToLoadClass(clsName).isDefined
val exists = entries.filter(_.hasExtension("class")).map(classNameOf).exists(alreadyDefined)
diff --git a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
index 28ddf2939c..ed69d449cb 100644
--- a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -23,6 +23,7 @@ trait InteractiveReader {
def readYesOrNo(prompt: String, alt: => Boolean): Boolean = readOneKey(prompt) match {
case 'y' => true
case 'n' => false
+ case -1 => false // EOF
case _ => alt
}
diff --git a/test/files/pos/t9086.scala b/test/files/pos/t9086.scala
new file mode 100644
index 0000000000..fba34ee226
--- /dev/null
+++ b/test/files/pos/t9086.scala
@@ -0,0 +1,8 @@
+class X[A](a: A)
+object Test {
+ implicit val ImplicitBoolean: Boolean = true
+ def local = {
+ implicit object X extends X({ implicitly[Boolean] ; "" })
+ implicitly[X[String]] // failed in 2.11.5
+ }
+}
diff --git a/test/files/run/t6502.check b/test/files/run/t6502.check
deleted file mode 100644
index 95d36ee221..0000000000
--- a/test/files/run/t6502.check
+++ /dev/null
@@ -1,8 +0,0 @@
-test1 res1: true
-test1 res2: true
-test2 res1: true
-test2 res2: true
-test3 res1: true
-test3 res2: true
-test4 res1: true
-test4 res2: true
diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala
index 4ce034a482..52fabef6b8 100644
--- a/test/files/run/t6502.scala
+++ b/test/files/run/t6502.scala
@@ -46,6 +46,12 @@ object Test extends StoreReporterDirectTest {
}
}"""
+ def app6 = """
+ package test6
+ class A extends Test { println("created test6.A") }
+ class Z extends Test { println("created test6.Z") }
+ trait Test"""
+
def test1(): Unit = {
val jar = "test1.jar"
compileCode(app1, jar)
@@ -53,11 +59,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "test.Test.test()")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("testing...")
-
- println(s"test1 res1: $res1")
- println(s"test1 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("testing...")
+ }
}
def test2(): Unit = {
@@ -69,11 +76,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar2")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
-
- println(s"test2 res1: $res1")
- println(s"test2 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ }
}
def test3(): Unit = {
@@ -85,11 +93,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar3", "test.Test3.test()")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("new object in existing package")
-
- println(s"test3 res1: $res1")
- println(s"test3 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("new object in existing package")
+ }
}
def test4(): Unit = {
@@ -98,11 +107,30 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar1")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ }
+ }
- println(s"test4 res1: $res1")
- println(s"test4 res2: $res2")
+ def test5(): Unit = {
+ val codeToRun = ":require /does/not/exist.jar"
+ val output = ILoop.run(codeToRun, settings)
+ assert(!output.contains("NullPointerException"), output)
+ assert(output.contains("Cannot load '/does/not/exist.jar'"), output)
+ }
+
+ def test6(): Unit = {
+ // Avoid java.lang.NoClassDefFoundError triggered by the old appoach of using a Java
+ // classloader to parse .class files in order to read their names.
+ val jar = "test6.jar"
+ compileCode(app6, jar)
+ val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "import test6._; new A; new Z")
+ val output = ILoop.run(codeToRun, settings)
+ assert(output.contains("created test6.A"), output)
+ assert(output.contains("created test6.Z"), output)
}
def show(): Unit = {
@@ -110,7 +138,9 @@ object Test extends StoreReporterDirectTest {
test2()
test3()
test4()
+ test5()
+ test6()
}
- def toCodeInSeparateLines(lines: String*): String = lines.map(_ + "\n").mkString
+ def toCodeInSeparateLines(lines: String*): String = lines mkString "\n"
}