diff --git a/compiler/src/dotty/tools/dotc/core/PhantomErasure.scala b/compiler/src/dotty/tools/dotc/core/PhantomErasure.scala
index 9821c69713c0..0e1e159846f7 100644
--- a/compiler/src/dotty/tools/dotc/core/PhantomErasure.scala
+++ b/compiler/src/dotty/tools/dotc/core/PhantomErasure.scala
@@ -2,7 +2,7 @@ package dotty.tools.dotc.core
import dotty.tools.dotc.ast.tpd._
import dotty.tools.dotc.core.Contexts.Context
-import dotty.tools.dotc.core.Symbols.defn
+import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core.Types.Type
/** Phantom erasure erases:
@@ -27,4 +27,7 @@ object PhantomErasure {
/** Returns the default erased tree for a phantom parameter ref */
def erasedParameterRef(implicit ctx: Context): Tree = ref(defn.ErasedPhantom_UNIT)
+ /** Is it a pure term inserted by the phantom erasure? */
+ def isErasedPhantom(sym: Symbol)(implicit ctx: Context): Boolean = sym eq defn.ErasedPhantom_UNIT
+
}
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
index f91f19b23014..2d653d581e3c 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
@@ -98,6 +98,7 @@ public enum ErrorMessageID {
ExpectedStartOfTopLevelDefinitionID,
MissingReturnTypeWithReturnStatementID,
NoReturnFromInlineID,
+ ReturnOutsideMethodDefinitionID,
;
public int errorNumber() {
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index b471a6b2453c..c6baa509f179 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -4,7 +4,7 @@ package reporting
package diagnostic
import dotc.core._
-import Contexts.Context
+import Contexts.{Context, NoContext}
import Decorators._
import Symbols._
import Names._
@@ -1747,4 +1747,14 @@ object messages {
|returned from a method.
|"""
}
+
+ case class ReturnOutsideMethodDefinition(owner: Symbol)(implicit ctx: Context)
+ extends Message(ReturnOutsideMethodDefinitionID) {
+ val kind = "Syntax"
+ val msg = hl"${"return"} outside method definition"
+ val explanation =
+ hl"""You used ${"return"} in ${owner}.
+ |${"return"} is a keyword and may only be used within method declarations.
+ |"""
+ }
}
diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala
index c8fc99ff6322..c78536c3b4fc 100644
--- a/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala
+++ b/compiler/src/dotty/tools/dotc/transform/localopt/Simplify.scala
@@ -11,6 +11,7 @@ import core.NameOps._
import transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo}
import config.Printers.simplify
import ast.tpd
+import dotty.tools.dotc.core.PhantomErasure
import scala.annotation.tailrec
@@ -62,6 +63,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
new Devalify ::
new Jumpjump ::
new DropGoodCasts ::
+ new DropNoEffects(this) ::
new ConstantFold(this) ::
Nil
@@ -174,13 +176,16 @@ object Simplify {
}
def isImmutableAccessor(t: Tree)(implicit ctx: Context): Boolean = {
- val isImmutableGetter = t.symbol.isGetter && !t.symbol.is(Mutable | Lazy)
- val isCaseAccessor = t.symbol.is(CaseAccessor) && !t.symbol.is(Mutable | Lazy)
- val isProductAccessor = t.symbol.exists &&
- t.symbol.owner.derivesFrom(defn.ProductClass) &&
- t.symbol.owner.is(CaseClass) &&
- t.symbol.name.isSelectorName &&
- !t.symbol.info.decls.exists(_.is(Mutable | Lazy)) // Conservatively covers case class A(var x: Int)
- isImmutableGetter || isCaseAccessor || isProductAccessor
+ val sym = t.symbol
+ val isImmutableGetter = sym.isGetter && !sym.is(Mutable | Lazy)
+ val isCaseAccessor = sym.is(CaseAccessor) && !sym.is(Mutable | Lazy)
+ val isProductAccessor = sym.exists &&
+ sym.owner.derivesFrom(defn.ProductClass) &&
+ sym.owner.is(CaseClass) &&
+ sym.name.isSelectorName &&
+ !sym.info.decls.exists(_.is(Mutable | Lazy)) // Conservatively covers case class A(var x: Int)
+ val isErasedPhantom = PhantomErasure.isErasedPhantom(sym)
+
+ isImmutableGetter || isCaseAccessor || isProductAccessor || isErasedPhantom
}
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index a69f509a677e..ab63b6f51580 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -979,8 +979,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def enclMethInfo(cx: Context): (Tree, Type) = {
val owner = cx.owner
- if (cx == NoContext || owner.isType) {
- ctx.error("return outside method definition", tree.pos)
+ if (owner.isType) {
+ ctx.error(ReturnOutsideMethodDefinition(owner), tree.pos)
(EmptyTree, WildcardType)
}
else if (owner != cx.outer.owner && owner.isRealMethod) {
diff --git a/compiler/test/dotc/comptest.scala b/compiler/test/dotc/comptest.scala
index 318f9cd80612..de9fb0b1e515 100644
--- a/compiler/test/dotc/comptest.scala
+++ b/compiler/test/dotc/comptest.scala
@@ -12,8 +12,6 @@ object comptest extends ParallelTesting {
def isInteractive = true
def testFilter = None
- implicit val defaultOutputDir: String = "."
-
val posDir = "./tests/pos/"
val negDir = "./tests/neg/"
val dotcDir = "./src/dotty/"
@@ -26,6 +24,7 @@ object comptest extends ParallelTesting {
dotcDir + "tools/dotc/core/Types.scala",
dotcDir + "tools/dotc/ast/Trees.scala"
),
- TestFlags("", Array("-Ylog:frontend", "-Xprompt"))
+ TestFlags("", Array("-Ylog:frontend", "-Xprompt")),
+ outDirectory = "."
)
}
diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala
index 2863bff4e48d..3eba2b1e7e8a 100644
--- a/compiler/test/dotty/tools/dotc/CompilationTests.scala
+++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala
@@ -15,6 +15,7 @@ import dotty.tools.io.JFile
class CompilationTests extends ParallelTesting {
+ import ParallelTesting._
import TestConfiguration._
import CompilationTests._
@@ -68,7 +69,6 @@ class CompilationTests extends ParallelTesting {
compileFilesInDir("../tests/pos-special/strawman-collections", defaultOptions) +
compileFile("../scala2-library/src/library/scala/collection/immutable/IndexedSeq.scala", defaultOptions) +
compileFile("../scala2-library/src/library/scala/collection/parallel/mutable/ParSetLike.scala", defaultOptions) +
- compileFile("../tests/pos/t2171.scala", defaultOptimised) +
compileList(
"parSetSubset",
List(
@@ -159,6 +159,7 @@ class CompilationTests extends ParallelTesting {
@Test def compileNeg: Unit = {
compileShallowFilesInDir("../tests/neg", defaultOptions) +
+ compileShallowFilesInDir("../tests/neg/no-optimise", defaultOptions) +
compileFile("../tests/neg/customArgs/typers.scala", allowDoubleBindings) +
compileFile("../tests/neg/customArgs/overrideClass.scala", scala2Mode) +
compileFile("../tests/neg/customArgs/autoTuplingTest.scala", defaultOptions.and("-language:noAutoTupling")) +
@@ -186,12 +187,7 @@ class CompilationTests extends ParallelTesting {
@Test def runAll: Unit = {
compileFilesInDir("../tests/run", defaultOptions) +
- compileFile("../tests/run/i3018.scala", defaultOptimised) +
- compileFile("../tests/run/blame_eye_triple_eee-double.scala", defaultOptimised) +
- compileFile("../tests/run/blame_eye_triple_eee-float.scala", defaultOptimised) +
- compileFile("../tests/run/run-bug4840.scala", defaultOptimised) +
- compileFile("../tests/run/optimizer-array-load.scala", defaultOptimised) +
- compileFile("../tests/run/constant-optimization.scala", defaultOptimised)
+ compileFilesInDir("../tests/run-no-optimise", defaultOptions)
}.checkRuns()
// Pickling Tests ------------------------------------------------------------
@@ -298,6 +294,13 @@ class CompilationTests extends ParallelTesting {
tests.foreach(_.delete())
}
+ @Test def testOptimised: Unit = {
+ val outputDir = defaultOutputDir + "optimised/"
+ compileFilesInDir("../tests/pos", defaultOptimised, outputDir).checkCompile()
+ compileFilesInDir("../tests/run", defaultOptimised, outputDir).checkRuns()
+ compileShallowFilesInDir("../tests/neg", defaultOptimised, outputDir).checkExpectedErrors()
+ }
+
private val (compilerSources, backendSources, backendJvmSources) = {
val compilerDir = Paths.get("../compiler/src")
val compilerSources0 = sources(Files.walk(compilerDir))
diff --git a/compiler/test/dotty/tools/dotc/LinkOptimiseTests.scala b/compiler/test/dotty/tools/dotc/LinkOptimiseTests.scala
index 70fa01c5f053..7aa2f0bcb651 100644
--- a/compiler/test/dotty/tools/dotc/LinkOptimiseTests.scala
+++ b/compiler/test/dotty/tools/dotc/LinkOptimiseTests.scala
@@ -13,6 +13,7 @@ import scala.concurrent.duration._
import scala.collection.JavaConverters._
class LinkOptimiseTests extends ParallelTesting {
+ import ParallelTesting._
import TestConfiguration._
import LinkOptimiseTests._
diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
index 90497f54f8b4..c00d971a83e6 100644
--- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
+++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
@@ -985,4 +985,18 @@ class ErrorMessagesTests extends ErrorMessagesTest {
val NoReturnFromInline(method) :: Nil = messages
assertEquals("method usesReturn", method.show)
}
+
+ @Test def returnOutsideMethodDefinition =
+ checkMessagesAfter("frontend") {
+ """object A {
+ | return 5
+ |}
+ """.stripMargin
+ }.expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ assertMessageCount(1, messages)
+ val ReturnOutsideMethodDefinition(owner) :: Nil = messages
+ assertEquals("object A", owner.show)
+ }
+
}
diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala
index b5534337e82b..2fad926c0a79 100644
--- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala
+++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala
@@ -1057,7 +1057,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
}
/** Compiles a single file from the string path `f` using the supplied flags */
- def compileFile(f: String, flags: TestFlags)(implicit outDirectory: String): CompilationTest = {
+ def compileFile(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val sourceFile = new JFile(f)
val parent = sourceFile.getParentFile
@@ -1087,7 +1087,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* By default, files are compiled in alphabetical order. An optional seed
* can be used for randomization.
*/
- def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None)(implicit outDirectory: String): CompilationTest = {
+ def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
val sourceDir = new JFile(f)
@@ -1116,7 +1116,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* `testName` since files can be in separate directories and or be otherwise
* dissociated
*/
- def compileList(testName: String, files: List[String], flags: TestFlags, callingMethod: String = getCallingMethod())(implicit outDirectory: String): CompilationTest = {
+ def compileList(testName: String, files: List[String], flags: TestFlags, callingMethod: String = getCallingMethod(), outDirectory: String = defaultOutputDir): CompilationTest = {
val outDir = outDirectory + callingMethod + "/" + testName + "/"
// Directories in which to compile all containing files with `flags`:
@@ -1147,7 +1147,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* - Directories can have an associated check-file, where the check file has
* the same name as the directory (with the file extension `.check`)
*/
- def compileFilesInDir(f: String, flags: TestFlags)(implicit outDirectory: String): CompilationTest = {
+ def compileFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
val sourceDir = new JFile(f)
@@ -1167,7 +1167,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* sub-directories and as such, does **not** perform separate compilation
* tests.
*/
- def compileShallowFilesInDir(f: String, flags: TestFlags)(implicit outDirectory: String): CompilationTest = {
+ def compileShallowFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
val sourceDir = new JFile(f)
@@ -1185,6 +1185,9 @@ trait ParallelTesting extends RunnerOrchestration { self =>
}
object ParallelTesting {
+
+ def defaultOutputDir: String = "../out/"
+
def isSourceFile(f: JFile): Boolean = {
val name = f.getName
name.endsWith(".scala") || name.endsWith(".java")
diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala
index 1c94ba230a10..9ebd7a6cae91 100644
--- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala
+++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala
@@ -3,7 +3,6 @@ package tools
package vulpix
object TestConfiguration {
- implicit val defaultOutputDir: String = "../out/"
val noCheckOptions = Array(
"-pagewidth", "120",
diff --git a/doc-tool/resources/_layouts/main.html b/doc-tool/resources/_layouts/main.html
index 364da6fb7ade..137d517f1bbf 100644
--- a/doc-tool/resources/_layouts/main.html
+++ b/doc-tool/resources/_layouts/main.html
@@ -61,5 +61,12 @@
}
});
+
+
+