summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala11
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala16
-rw-r--r--test/files/pos/t7584.scala11
-rw-r--r--test/files/run/t6308.scala20
-rw-r--r--test/files/run/t7584.check6
-rw-r--r--test/files/run/t7584.flags1
-rw-r--r--test/files/run/t7584.scala14
7 files changed, 67 insertions, 12 deletions
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 30ec555bc5..5c92512193 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -98,7 +98,7 @@ abstract class TreeInfo {
*/
def isStableIdentifier(tree: Tree, allowVolatile: Boolean): Boolean =
tree match {
- case Ident(_) => symOk(tree.symbol) && tree.symbol.isStable && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec
+ case i @ Ident(_) => isStableIdent(i)
case Select(qual, _) => isStableMemberOf(tree.symbol, qual, allowVolatile) && isPath(qual, allowVolatile)
case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX =>
// see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm`
@@ -119,6 +119,13 @@ abstract class TreeInfo {
typeOk(tree.tpe) && (allowVolatile || !hasVolatileType(tree)) && !definitions.isByNameParamType(tree.tpe)
)
+ private def isStableIdent(tree: Ident): Boolean = (
+ symOk(tree.symbol)
+ && tree.symbol.isStable
+ && !definitions.isByNameParamType(tree.tpe)
+ && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec
+ )
+
/** Is `tree`'s type volatile? (Ignored if its symbol has the @uncheckedStable annotation.)
*/
def hasVolatileType(tree: Tree): Boolean =
@@ -201,7 +208,7 @@ abstract class TreeInfo {
}
def isWarnableSymbol = {
val sym = tree.symbol
- (sym == null) || !(sym.isModule || sym.isLazy) || {
+ (sym == null) || !(sym.isModule || sym.isLazy || definitions.isByNameParamType(sym.tpe_*)) || {
debuglog("'Pure' but side-effecting expression in statement position: " + tree)
false
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 8ec8b2ed5f..a84d076e76 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -22,6 +22,7 @@ import scala.reflect.classTag
import StdReplTags._
import scala.concurrent.{ ExecutionContext, Await, Future, future }
import ExecutionContext.Implicits._
+import scala.reflect.internal.util.BatchSourceFile
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
@@ -530,8 +531,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
def pasteCommand(): Result = {
echo("// Entering paste mode (ctrl-D to finish)\n")
val code = readWhile(_ => true) mkString "\n"
- echo("\n// Exiting paste mode, now interpreting.\n")
- intp interpret code
+ if (code.trim.isEmpty) {
+ echo("\n// Nothing pasted, nothing gained.\n")
+ } else {
+ echo("\n// Exiting paste mode, now interpreting.\n")
+ val res = intp interpret code
+ // if input is incomplete, let the compiler try to say why
+ if (res == IR.Incomplete) {
+ echo("The pasted code is incomplete!\n")
+ // Remembrance of Things Pasted in an object
+ val errless = intp compileSources new BatchSourceFile("<pastie>", s"object pastel {\n$code\n}")
+ if (errless) echo("...but compilation found no error? Good luck with that.")
+ }
+ }
()
}
diff --git a/test/files/pos/t7584.scala b/test/files/pos/t7584.scala
new file mode 100644
index 0000000000..52d127ecb9
--- /dev/null
+++ b/test/files/pos/t7584.scala
@@ -0,0 +1,11 @@
+object Test {
+ def fold[A, B](f: (A, => B) => B) = ???
+ def f[A, B](x: A, y: B): B = ???
+ def bip[A, B] = fold[A, B]((x, y) => f(x, y))
+ def bop[A, B] = fold[A, B](f)
+
+ // these work:
+ fold[Int, Int]((x, y) => f(x, y))
+ fold[Int, Int](f)
+}
+
diff --git a/test/files/run/t6308.scala b/test/files/run/t6308.scala
index bcd89359b0..d23cd6e13e 100644
--- a/test/files/run/t6308.scala
+++ b/test/files/run/t6308.scala
@@ -1,21 +1,25 @@
import scala.{specialized => sp}
+// NOTE: `{ val c = caller; print(""); c }` is used instead of a simple `caller`,
+// because we want to prevent tail-call optimization from eliding the stack-
+// frames we want to inspect.
+
object Test {
def caller = new Exception().getStackTrace()(1).getMethodName
- def f1[@sp(Int) A](a: A, b: Any) = caller
- def f2[@sp(Int) A, B](a: A, b: String) = caller
- def f3[B, @sp(Int) A](a: A, b: List[B]) = caller
- def f4[B, @sp(Int) A](a: A, b: List[(A, B)]) = caller
+ def f1[@sp(Int) A](a: A, b: Any) = { val c = caller; print(""); c }
+ def f2[@sp(Int) A, B](a: A, b: String) = { val c = caller; print(""); c }
+ def f3[B, @sp(Int) A](a: A, b: List[B]) = { val c = caller; print(""); c }
+ def f4[B, @sp(Int) A](a: A, b: List[(A, B)]) = { val c = caller; print(""); c }
- def f5[@sp(Int) A, B <: Object](a: A, b: B) = caller
+ def f5[@sp(Int) A, B <: Object](a: A, b: B) = { val c = caller; print(""); c }
// `uncurryTreeType` calls a TypeMap on the call to this method and we end up with new
// type parameter symbols, which are not found in `TypeEnv.includes(typeEnv(member), env)`
// in `specSym`. (One of `uncurry`'s tasks is to expand type aliases in signatures.)
type T = Object
- def todo1[@sp(Int) A, B <: T](a: A, b: String) = caller
- def todo2[@sp(Int) A, B <: AnyRef](a: A, b: String) = caller
- def todo3[B <: List[A], @specialized(Int) A](a: A, b: B) = caller
+ def todo1[@sp(Int) A, B <: T](a: A, b: String) = { val c = caller; print(""); c }
+ def todo2[@sp(Int) A, B <: AnyRef](a: A, b: String) = { val c = caller; print(""); c }
+ def todo3[B <: List[A], @specialized(Int) A](a: A, b: B) = { val c = caller; print(""); c }
def main(args: Array[String]) {
val s = ""
diff --git a/test/files/run/t7584.check b/test/files/run/t7584.check
new file mode 100644
index 0000000000..9f53e5dde5
--- /dev/null
+++ b/test/files/run/t7584.check
@@ -0,0 +1,6 @@
+no calls
+call A
+a
+call B twice
+b
+b
diff --git a/test/files/run/t7584.flags b/test/files/run/t7584.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/run/t7584.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/run/t7584.scala b/test/files/run/t7584.scala
new file mode 100644
index 0000000000..6d7f4f7ebb
--- /dev/null
+++ b/test/files/run/t7584.scala
@@ -0,0 +1,14 @@
+// Test case added to show the behaviour of functions with
+// by-name parameters. The evaluation behaviour was already correct.
+//
+// We did flush out a spurious "pure expression does nothing in statement position"
+// warning, hence -Xfatal-warnings in the flags file.
+object Test extends App {
+ def foo(f: (=> Int, => Int) => Unit) = f({println("a"); 0}, {println("b"); 1})
+ println("no calls")
+ foo((a, b) => ())
+ println("call A")
+ foo((a, b) => a)
+ println("call B twice")
+ foo((a, b) => {b; b})
+}