From f0d913b51dbe1a098e813aa08197eef9c6cbf737 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 10 Dec 2013 11:04:26 +0100 Subject: SI-8062 Fix inliner cycle with recursion, separate compilation ICodeReaders, which decompiles JVM bytecode to ICode, was not setting the `recursive` attribute of `IMethod`. This meant that the inliner got into a cycle, repeatedly inlining the recursive call. The method name `filter` was needed to trigger this as the inliner heuristically treats that as a more attractive inlining candidate, based on `isMonadicMethod`. This commit: - refactors the checking / setting of `virtual` - adds this to ICodeReaders - tests the case involving `invokevirtual` I'm not sure how to setup a test that fails without the other changes to `ICodeReader` (for invokestatic and invokespecial). --- src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 5 +---- src/compiler/scala/tools/nsc/backend/icode/Members.scala | 4 ++++ src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala | 7 ++++++- test/files/pos/t8062.flags | 1 + test/files/pos/t8062/A_1.scala | 5 +++++ test/files/pos/t8062/B_2.scala | 3 +++ 6 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test/files/pos/t8062.flags create mode 100644 test/files/pos/t8062/A_1.scala create mode 100644 test/files/pos/t8062/B_2.scala diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 44d7a1929b..71a5b85271 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -954,10 +954,7 @@ abstract class GenICode extends SubComponent { case _ => } ctx1.bb.emit(cm, tree.pos) - - if (sym == ctx1.method.symbol) { - ctx1.method.recursive = true - } + ctx1.method.updateRecursive(sym) generatedType = if (sym.isClassConstructor) UNIT else toTypeKind(sym.info.resultType); diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index b74770f051..00bcf603cf 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -185,6 +185,10 @@ trait Members { this } + final def updateRecursive(called: Symbol): Unit = { + recursive ||= (called == symbol) + } + def addLocal(l: Local): Local = findOrElse(locals)(_ == l) { locals ::= l ; l } def addParam(p: Local): Unit = diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index c304c18c4f..d0c540a2c6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -489,23 +489,28 @@ abstract class ICodeReader extends ClassfileParser { case JVM.invokevirtual => val m = pool.getMemberSymbol(in.nextChar, false); size += 2 code.emit(CALL_METHOD(m, Dynamic)) + method.updateRecursive(m) case JVM.invokeinterface => val m = pool.getMemberSymbol(in.nextChar, false); size += 4 in.skip(2) code.emit(CALL_METHOD(m, Dynamic)) + // invokeinterface can't be recursive case JVM.invokespecial => val m = pool.getMemberSymbol(in.nextChar, false); size += 2 val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(true) else SuperCall(m.owner.name); code.emit(CALL_METHOD(m, style)) + method.updateRecursive(m) case JVM.invokestatic => val m = pool.getMemberSymbol(in.nextChar, true); size += 2 if (isBox(m)) code.emit(BOX(toTypeKind(m.info.paramTypes.head))) else if (isUnbox(m)) code.emit(UNBOX(toTypeKind(m.info.resultType))) - else + else { code.emit(CALL_METHOD(m, Static(false))) + method.updateRecursive(m) + } case JVM.invokedynamic => // TODO, this is just a place holder. A real implementation must parse the class constant entry debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.") diff --git a/test/files/pos/t8062.flags b/test/files/pos/t8062.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/pos/t8062.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/pos/t8062/A_1.scala b/test/files/pos/t8062/A_1.scala new file mode 100644 index 0000000000..ca0411dae8 --- /dev/null +++ b/test/files/pos/t8062/A_1.scala @@ -0,0 +1,5 @@ +package warmup + +object Warmup { + def filter[A](p: Any => Boolean): Any = filter[Any](p) +} diff --git a/test/files/pos/t8062/B_2.scala b/test/files/pos/t8062/B_2.scala new file mode 100644 index 0000000000..f0a6761488 --- /dev/null +++ b/test/files/pos/t8062/B_2.scala @@ -0,0 +1,3 @@ +object Test { + warmup.Warmup.filter[Any](x => false) +} -- cgit v1.2.3 From 47562e7adbf8577789b3432f4bfbb36d786c6b32 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 10 Dec 2013 15:50:20 -0800 Subject: Revert "SI-6426, importable _." This reverts commit d2316df920ffa4804fe51e8f8780240c46efa982. We can't make `_` an illegal identifier -- it's legal in Java, so we must be able to name these Java underscores. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 7 +++++-- src/compiler/scala/tools/nsc/ast/parser/Scanners.scala | 5 +---- test/files/neg/t6426.check | 7 ------- test/files/neg/t6426.scala | 5 ----- 4 files changed, 6 insertions(+), 18 deletions(-) delete mode 100644 test/files/neg/t6426.check delete mode 100644 test/files/neg/t6426.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 996287dea8..b9e4109623 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -980,8 +980,11 @@ self => /** Assumed (provisionally) to be TermNames. */ def ident(skipIt: Boolean): Name = - if (isIdent) rawIdent().encode - else { + if (isIdent) { + val name = in.name.encode + in.nextToken() + name + } else { syntaxErrorOrIncomplete(expectedMsg(IDENTIFIER), skipIt) nme.ERROR } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 1aa50be83a..8d295a28d0 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -611,10 +611,7 @@ trait Scanners extends ScannersCommon { if (ch == '`') { nextChar() finishNamed(BACKQUOTED_IDENT) - if (name.length == 0) - syntaxError("empty quoted identifier") - else if (name == nme.WILDCARD) - syntaxError("wildcard invalid as backquoted identifier") + if (name.length == 0) syntaxError("empty quoted identifier") } else syntaxError("unclosed quoted identifier") } diff --git a/test/files/neg/t6426.check b/test/files/neg/t6426.check deleted file mode 100644 index 149f74c4de..0000000000 --- a/test/files/neg/t6426.check +++ /dev/null @@ -1,7 +0,0 @@ -t6426.scala:4: error: wildcard invalid as backquoted identifier - println(`_`.Buffer(0)) - ^ -t6426.scala:5: error: ')' expected but '}' found. -} -^ -two errors found diff --git a/test/files/neg/t6426.scala b/test/files/neg/t6426.scala deleted file mode 100644 index a27d18eb58..0000000000 --- a/test/files/neg/t6426.scala +++ /dev/null @@ -1,5 +0,0 @@ -class A { - import collection.{mutable => _, _} - - println(`_`.Buffer(0)) -} -- cgit v1.2.3 From 2aa9da578e03987427a2d932becc75fc0f016d8b Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 11 Dec 2013 15:15:56 -0800 Subject: Partially revert f8d8f7d08d. Need `${dist.dir}/lib/scala-partest.jar` for maven publish. We still don't want to distribute it in the distribution, but will have to remove it in release script, as 2.10.x's build hasn't been refactoreded like master's, and I'm not backporting it. --- build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build.xml b/build.xml index 377a0c958b..39685163a6 100644 --- a/build.xml +++ b/build.xml @@ -1837,6 +1837,7 @@ TODO: + -- cgit v1.2.3 From 3fa2c97853de2110227f50982187b4377b8772bc Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 11 Dec 2013 17:05:41 -0800 Subject: Report error on code size overflow, log method name. We used to silently skip class files that would exceed the JVM's size limits. While rare, this should still be an error. While I was at it, also included the name of the offending method. --- src/asm/scala/tools/asm/MethodWriter.java | 7 ++++++- .../scala/tools/nsc/backend/jvm/GenASM.scala | 9 ++++---- test/files/run/large_code.check | 3 +++ test/files/run/large_code.scala | 24 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 test/files/run/large_code.check create mode 100644 test/files/run/large_code.scala diff --git a/src/asm/scala/tools/asm/MethodWriter.java b/src/asm/scala/tools/asm/MethodWriter.java index 321bacb6fc..887cb28c6f 100644 --- a/src/asm/scala/tools/asm/MethodWriter.java +++ b/src/asm/scala/tools/asm/MethodWriter.java @@ -1853,7 +1853,12 @@ class MethodWriter extends MethodVisitor { int size = 8; if (code.length > 0) { if (code.length > 65536) { - throw new RuntimeException("Method code too large!"); + String nameString = ""; + int i = 0; + // find item that corresponds to the index of our name + while (i < cw.items.length && (cw.items[i] == null || cw.items[i].index != name)) i++; + if (cw.items[i] != null) nameString = cw.items[i].strVal1 +"'s "; + throw new RuntimeException("Method "+ nameString +"code too large!"); } cw.newUTF8("Code"); size += 18 + code.length + 8 * handlerCount; diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 97140aca2e..19cdcd2590 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -450,7 +450,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { } // ----------------------------------------------------------------------------------------- - // utitilies useful when emitting plain, mirror, and beaninfo classes. + // utilities useful when emitting plain, mirror, and beaninfo classes. // ----------------------------------------------------------------------------------------- def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) { @@ -458,9 +458,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val arr = jclass.toByteArray() bytecodeWriter.writeClass(label, jclassName, arr, sym) } catch { - case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") => - // TODO check where ASM throws the equivalent of CodeSizeTooBigException - log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).") + case e: java.lang.RuntimeException if e != null && (e.getMessage contains "too large!") => + reporter.error(sym.pos, + s"Could not write class $jclassName because it exceeds JVM code size limits. ${e.getMessage}") } } @@ -1402,7 +1402,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { addInnerClasses(clasz.symbol, jclass) jclass.visitEnd() writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol) - } /** diff --git a/test/files/run/large_code.check b/test/files/run/large_code.check new file mode 100644 index 0000000000..6ad50967bc --- /dev/null +++ b/test/files/run/large_code.check @@ -0,0 +1,3 @@ +newSource1.scala:1: error: Could not write class BigEnoughToFail because it exceeds JVM code size limits. Method tooLong's code too large! +class BigEnoughToFail { + ^ diff --git a/test/files/run/large_code.scala b/test/files/run/large_code.scala new file mode 100644 index 0000000000..f9d7f8c95b --- /dev/null +++ b/test/files/run/large_code.scala @@ -0,0 +1,24 @@ +import scala.tools.partest._ +import java.io.{Console => _, _} + +// a cold run of partest takes about 15s for this test on my laptop +object Test extends DirectTest { + override def extraSettings: String = "-usejavacp -d " + testOutput.path + + // test that we hit the code size limit and error out gracefully + // 5958 is the magic number (2^16/11 -- each `a(1,2,3,4,5,6)` is 11 bytes of bytecode) + override def code + = s""" + |class BigEnoughToFail { + | def a(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int): Unit = {} + | def tooLong: Unit = { + | ${(1 to 5958) map (_ => "a(1,2,3,4,5,6)") mkString(";")} + | } + |}""".stripMargin.trim + + override def show(): Unit = { + Console.withErr(System.out) { + compile() + } + } +} -- cgit v1.2.3 From a12dd9c3b6fb4a767eec8f6d3bf0a9a2266eff85 Mon Sep 17 00:00:00 2001 From: Mirco Dotta Date: Tue, 10 Dec 2013 17:12:58 +0100 Subject: Test demonstrating SI-8085 * The presentation compiler sourcepath is now correctly set-up. * Amazingly enough (for me at least), the outer import in the package object seem to be responsible of the faulty behavior. In fact, if you move the import clause *inside* the package object, the test succeed! The test's output does provide the correct hint of this: ``` % diff /Users/mirco/Projects/ide/scala/test/files/presentation/t8085-presentation.log /Users/mirco/Projects/ide/scala/test/files/presentation/t8085.check @@ -1,3 +1,2 @@ reload: NodeScalaSuite.scala -prefixes differ: .nodescala,nodescala -value always is not a member of object scala.concurrent.Future +Test OK ``` Notice the ``-prefixes differ: .nodescala,nodescala``. And compare it with the output when the import clause is placed inside the package object: ``` % diff /Users/mirco/Projects/ide/scala/test/files/presentation/t8085-presentation.log /Users/mirco/Projects/ide/scala/test/files/presentation/t8085.check @@ -1,4 +1,2 @@ reload: NodeScalaSuite.scala -reload: NodeScalaSuite.scala -open package module: package object nodescala Test OK ``` Notice now the ``-open package module: package object nodescala``! --- test/files/presentation/t8085.check | 3 +++ test/files/presentation/t8085.flags | 1 + test/files/presentation/t8085/Test.scala | 28 ++++++++++++++++++++++ .../presentation/t8085/src/nodescala/Foo.scala | 3 +++ .../t8085/src/nodescala/NodeScalaSuite.scala | 12 ++++++++++ .../presentation/t8085/src/nodescala/package.scala | 8 +++++++ 6 files changed, 55 insertions(+) create mode 100644 test/files/presentation/t8085.check create mode 100644 test/files/presentation/t8085.flags create mode 100644 test/files/presentation/t8085/Test.scala create mode 100644 test/files/presentation/t8085/src/nodescala/Foo.scala create mode 100644 test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala create mode 100644 test/files/presentation/t8085/src/nodescala/package.scala diff --git a/test/files/presentation/t8085.check b/test/files/presentation/t8085.check new file mode 100644 index 0000000000..46aac791f5 --- /dev/null +++ b/test/files/presentation/t8085.check @@ -0,0 +1,3 @@ +reload: NodeScalaSuite.scala +prefixes differ: .nodescala,nodescala +value always is not a member of object scala.concurrent.Future diff --git a/test/files/presentation/t8085.flags b/test/files/presentation/t8085.flags new file mode 100644 index 0000000000..ec35b223d8 --- /dev/null +++ b/test/files/presentation/t8085.flags @@ -0,0 +1 @@ +-sourcepath src diff --git a/test/files/presentation/t8085/Test.scala b/test/files/presentation/t8085/Test.scala new file mode 100644 index 0000000000..5d11009818 --- /dev/null +++ b/test/files/presentation/t8085/Test.scala @@ -0,0 +1,28 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + // loadSourceAndWaitUntilTypechecked("package.scala") // <-- uncomment this line and the test succeed + val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") + checkErrors(src) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + askReload(List(sourceFile)).get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/t8085/src/nodescala/Foo.scala b/test/files/presentation/t8085/src/nodescala/Foo.scala new file mode 100644 index 0000000000..19efdb65dd --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/Foo.scala @@ -0,0 +1,3 @@ +package nodescala + +class Foo diff --git a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala new file mode 100644 index 0000000000..a8803ff86d --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala @@ -0,0 +1,12 @@ +package nodescala + +import scala.concurrent.Future + +class NodeScalaSuite { + Future.always(517) + + // This is here only to prove that the presentation compiler is instantiated with the + // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in + // the test's output + println(new Foo()) +} \ No newline at end of file diff --git a/test/files/presentation/t8085/src/nodescala/package.scala b/test/files/presentation/t8085/src/nodescala/package.scala new file mode 100644 index 0000000000..6e9d4b729a --- /dev/null +++ b/test/files/presentation/t8085/src/nodescala/package.scala @@ -0,0 +1,8 @@ +import scala.concurrent.Future // <-- if you move the import *inside* the package object, then it all works fine!! + +package object nodescala { + implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal { + def always[T](value: T): Future[T] = Promise[T].success(value).future + } +} + -- cgit v1.2.3 From 7e85b595502974bebf2f2625c6bc3645f0d3ab27 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 17 Dec 2013 17:47:15 +0100 Subject: SI-8085 Fix BrowserTraverser for package objects A source file like: import foo.bar package object baz Is parsed into: package { import foo.bar package baz { object `package` } } A special case in Namers compensates by adjusting the owner of `baz` to be ``, rather than ``. This wasn't being accounted for in `BrowserTraverser`, which underpins `-sourcepath`, and allows the presentation compiler to load top level symbols from sources outside those passes as the list of sources to compile. This bug did not appear in sources like: package p1 package object p2 { ... } ... because the parser does not wrap this in the `package {}` This goes some way to explaining why it has gone unnoticed for so long. --- .../scala/tools/nsc/symtab/BrowsingLoaders.scala | 6 +++-- test/files/presentation/t8085.check | 4 ++-- test/files/presentation/t8085/Test.scala | 1 - .../t8085/src/nodescala/NodeScalaSuite.scala | 6 ++--- .../presentation/t8085/src/nodescala/package.scala | 7 +++--- test/files/presentation/t8085b.check | 3 +++ test/files/presentation/t8085b.flags | 1 + test/files/presentation/t8085b/Test.scala | 27 ++++++++++++++++++++++ .../presentation/t8085b/src/p1/nodescala/Foo.scala | 4 ++++ .../t8085b/src/p1/nodescala/NodeScalaSuite.scala | 11 +++++++++ .../t8085b/src/p1/nodescala/package.scala | 9 ++++++++ 11 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 test/files/presentation/t8085b.check create mode 100644 test/files/presentation/t8085b.flags create mode 100644 test/files/presentation/t8085b/Test.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/Foo.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/package.scala diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index f2aab36b51..c7bd678385 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -64,8 +64,10 @@ abstract class BrowsingLoaders extends SymbolLoaders { addPackagePrefix(pre) packagePrefix += ("." + name) case Ident(name) => - if (packagePrefix.length != 0) packagePrefix += "." - packagePrefix += name + if (name != nme.EMPTY_PACKAGE_NAME) { // mirrors logic in Namers, see createPackageSymbol + if (packagePrefix.length != 0) packagePrefix += "." + packagePrefix += name + } case _ => throw new MalformedInput(pkg.pos.point, "illegal tree node in package prefix: "+pkg) } diff --git a/test/files/presentation/t8085.check b/test/files/presentation/t8085.check index 46aac791f5..79c1b2aa17 100644 --- a/test/files/presentation/t8085.check +++ b/test/files/presentation/t8085.check @@ -1,3 +1,3 @@ reload: NodeScalaSuite.scala -prefixes differ: .nodescala,nodescala -value always is not a member of object scala.concurrent.Future +open package module: package nodescala +Test OK diff --git a/test/files/presentation/t8085/Test.scala b/test/files/presentation/t8085/Test.scala index 5d11009818..e46b7ab8c8 100644 --- a/test/files/presentation/t8085/Test.scala +++ b/test/files/presentation/t8085/Test.scala @@ -5,7 +5,6 @@ import scala.tools.nsc.interactive.Response object Test extends InteractiveTest { override def execute(): Unit = { - // loadSourceAndWaitUntilTypechecked("package.scala") // <-- uncomment this line and the test succeed val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") checkErrors(src) } diff --git a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala index a8803ff86d..45e43c7afb 100644 --- a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala +++ b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala @@ -1,12 +1,10 @@ package nodescala -import scala.concurrent.Future - class NodeScalaSuite { - Future.always(517) + "".rich // This is here only to prove that the presentation compiler is instantiated with the // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in // the test's output println(new Foo()) -} \ No newline at end of file +} diff --git a/test/files/presentation/t8085/src/nodescala/package.scala b/test/files/presentation/t8085/src/nodescala/package.scala index 6e9d4b729a..26fb9f08e4 100644 --- a/test/files/presentation/t8085/src/nodescala/package.scala +++ b/test/files/presentation/t8085/src/nodescala/package.scala @@ -1,8 +1,7 @@ -import scala.concurrent.Future // <-- if you move the import *inside* the package object, then it all works fine!! +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! package object nodescala { - implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal { - def always[T](value: T): Future[T] = Promise[T].success(value).future + implicit class StringOps(val f: String) { + def rich = 0 } } - diff --git a/test/files/presentation/t8085b.check b/test/files/presentation/t8085b.check new file mode 100644 index 0000000000..79c1b2aa17 --- /dev/null +++ b/test/files/presentation/t8085b.check @@ -0,0 +1,3 @@ +reload: NodeScalaSuite.scala +open package module: package nodescala +Test OK diff --git a/test/files/presentation/t8085b.flags b/test/files/presentation/t8085b.flags new file mode 100644 index 0000000000..ec35b223d8 --- /dev/null +++ b/test/files/presentation/t8085b.flags @@ -0,0 +1 @@ +-sourcepath src diff --git a/test/files/presentation/t8085b/Test.scala b/test/files/presentation/t8085b/Test.scala new file mode 100644 index 0000000000..e46b7ab8c8 --- /dev/null +++ b/test/files/presentation/t8085b/Test.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") + checkErrors(src) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + askReload(List(sourceFile)).get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala new file mode 100644 index 0000000000..8ed1ada6b6 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala @@ -0,0 +1,4 @@ +package p1 +package nodescala + +class Foo diff --git a/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala new file mode 100644 index 0000000000..f6da67bdc7 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala @@ -0,0 +1,11 @@ +package p1 +package nodescala + +class NodeScalaSuite { + "".rich + + // This is here only to prove that the presentation compiler is instantiated with the + // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in + // the test's output + println(new Foo()) +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/package.scala b/test/files/presentation/t8085b/src/p1/nodescala/package.scala new file mode 100644 index 0000000000..cc383f1bab --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/package.scala @@ -0,0 +1,9 @@ +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! + +package p1 { + package object nodescala { + implicit class StringOps(val f: String) { + def rich = 0 + } + } +} -- cgit v1.2.3