From 4af9f1566dde56adecdba2690df71e39552e32fe Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Jan 2016 21:38:28 +0100 Subject: Re-write and Re-enable optimizer tests Rewrite tests for new optimizer - SI-6941 - SI-2171 - t3430 - t3252 - t4840 - t2171 - t3430 - t3252 - t6157 - t6547 - t8062 - t8306 - t8359 - t9123 - trait-force-info - private-inline test cases for bugs fixed in the new optimizer - SI-9160, the unnecessary boxing mentioned in the ticket is optimzied since push-pop elimination (#4858). - SI-8796 - SI-8524 - SI-7807 fix flags file for t3420 remove an empty flags file remove unnecessary partest filters explicit inliner warnings in test t7582 Restore the lisp test. Removing the flags file - our build runs with the (new) optimizer enabled anyway. The test spent the past few years as an optimizer test in pos/ see https://issues.scala-lang.org/browse/SI-4512. The attempt may fail, but why not give it a try. $ git lg -S"lisp" ... | * | | | f785785 - SI-4579 Yoke the power of lisp.scala as a stress for the optimizer. (3 years, 8 months ago) ... * | | | | | | 622cc99 - Revert the lisp test. (3 years, 10 months ago) ... * | | | | | | 97f0324 - Revived the lisp test. (3 years, 10 months ago) ... * | 1e0f7dc - Imprison the lisp test, no review. (4 years, 4 months ago) ... * | 6b09630 - "Freed the lisp test." Tweaked partest defaults... (4 years, 6 months ago) ... * | fec42c1 - Lisp test wins again, no review. (4 years, 8 months ago) ... * | 1c2d44d - Restored the lisp.scala test. (4 years, 8 months ago) ... * | 15ed892 - Temporarily sending lisp.scala to be interprete... (4 years, 8 months ago) ... --- test/files/jvm/t6941.check | 1 - test/files/jvm/t6941.flags | 1 - test/files/jvm/t6941/Analyzed_1.flags | 1 - test/files/jvm/t6941/Analyzed_1.scala | 11 - test/files/jvm/t6941/test.scala | 15 - test/files/pos/t2171.flags | 1 - test/files/pos/t2171.scala | 7 - test/files/pos/t3252.flags | 1 - test/files/pos/t3252.scala | 15 - test/files/pos/t3420.flags | 2 +- test/files/pos/t3430.flags | 1 - test/files/pos/t3430.scala | 13 - test/files/pos/t4579.flags | 1 - test/files/pos/t4579.scala | 518 --------------------- test/files/pos/t4840.flags | 2 +- test/files/pos/t6157.flags | 1 - test/files/pos/t6157.scala | 25 - test/files/pos/t6547.flags | 1 - test/files/pos/t6547.scala | 6 - test/files/pos/t8062.flags | 1 - test/files/pos/t8062/A_1.scala | 5 - test/files/pos/t8062/B_2.scala | 3 - test/files/pos/t8306.flags | 1 - test/files/pos/t8306.scala | 8 - test/files/pos/t8359-closelim-crash.flags | 1 - test/files/pos/t8359-closelim-crash.scala | 23 - test/files/pos/t9123.flags | 1 - test/files/pos/t9123.scala | 10 - test/files/pos/trait-force-info.flags | 1 - test/files/pos/trait-force-info.scala | 18 - test/files/run/elidable-opt.scala | 3 - test/files/run/lisp.check | 26 ++ test/files/run/lisp.scala | 518 +++++++++++++++++++++ test/files/run/t7008-scala-defined.flags | 0 test/files/run/t7008-scala-defined/Test_3.scala | 3 - test/files/run/t7582.check | 5 + test/files/run/t7582.flags | 2 +- test/files/run/t7582/InlineHolder.scala | 3 - test/files/run/t7582b.check | 5 + test/files/run/t7582b.flags | 2 +- test/files/run/t7582b/InlineHolder.scala | 3 - test/files/run/t7807.check | 3 + test/files/run/t7807.scala | 21 + .../junit/scala/issues/OptimizedBytecodeTest.scala | 331 +++++++++++++ .../nsc/transform/patmat/PatmatBytecodeTest.scala | 25 + test/pending/run/private-inline.check | 13 - test/pending/run/private-inline.flags | 1 - test/pending/run/private-inline.scala | 52 --- 48 files changed, 938 insertions(+), 773 deletions(-) delete mode 100644 test/files/jvm/t6941.check delete mode 100644 test/files/jvm/t6941.flags delete mode 100644 test/files/jvm/t6941/Analyzed_1.flags delete mode 100644 test/files/jvm/t6941/Analyzed_1.scala delete mode 100644 test/files/jvm/t6941/test.scala delete mode 100644 test/files/pos/t2171.flags delete mode 100644 test/files/pos/t2171.scala delete mode 100644 test/files/pos/t3252.flags delete mode 100644 test/files/pos/t3252.scala delete mode 100644 test/files/pos/t3430.flags delete mode 100644 test/files/pos/t3430.scala delete mode 100644 test/files/pos/t4579.flags delete mode 100644 test/files/pos/t4579.scala delete mode 100644 test/files/pos/t6157.flags delete mode 100644 test/files/pos/t6157.scala delete mode 100644 test/files/pos/t6547.flags delete mode 100644 test/files/pos/t6547.scala delete mode 100644 test/files/pos/t8062.flags delete mode 100644 test/files/pos/t8062/A_1.scala delete mode 100644 test/files/pos/t8062/B_2.scala delete mode 100644 test/files/pos/t8306.flags delete mode 100644 test/files/pos/t8306.scala delete mode 100644 test/files/pos/t8359-closelim-crash.flags delete mode 100644 test/files/pos/t8359-closelim-crash.scala delete mode 100644 test/files/pos/t9123.flags delete mode 100644 test/files/pos/t9123.scala delete mode 100644 test/files/pos/trait-force-info.flags delete mode 100644 test/files/pos/trait-force-info.scala create mode 100644 test/files/run/lisp.check create mode 100644 test/files/run/lisp.scala delete mode 100644 test/files/run/t7008-scala-defined.flags create mode 100644 test/files/run/t7807.check create mode 100644 test/files/run/t7807.scala create mode 100644 test/junit/scala/issues/OptimizedBytecodeTest.scala delete mode 100644 test/pending/run/private-inline.check delete mode 100644 test/pending/run/private-inline.flags delete mode 100644 test/pending/run/private-inline.scala (limited to 'test') diff --git a/test/files/jvm/t6941.check b/test/files/jvm/t6941.check deleted file mode 100644 index 43f53aba12..0000000000 --- a/test/files/jvm/t6941.check +++ /dev/null @@ -1 +0,0 @@ -bytecode identical diff --git a/test/files/jvm/t6941.flags b/test/files/jvm/t6941.flags deleted file mode 100644 index 49d036a887..0000000000 --- a/test/files/jvm/t6941.flags +++ /dev/null @@ -1 +0,0 @@ --optimize diff --git a/test/files/jvm/t6941/Analyzed_1.flags b/test/files/jvm/t6941/Analyzed_1.flags deleted file mode 100644 index ad51758c39..0000000000 --- a/test/files/jvm/t6941/Analyzed_1.flags +++ /dev/null @@ -1 +0,0 @@ --nowarn diff --git a/test/files/jvm/t6941/Analyzed_1.scala b/test/files/jvm/t6941/Analyzed_1.scala deleted file mode 100644 index b6951f71ee..0000000000 --- a/test/files/jvm/t6941/Analyzed_1.scala +++ /dev/null @@ -1,11 +0,0 @@ -// this class's bytecode, compiled under -optimize is analyzed by the test -// method a's bytecode should be identical to method b's bytecode -class SameBytecode { - def a(xs: List[Int]) = xs match { - case x :: _ => x - } - - def b(xs: List[Int]) = xs match { - case xs: ::[Int] => xs.head - } -} \ No newline at end of file diff --git a/test/files/jvm/t6941/test.scala b/test/files/jvm/t6941/test.scala deleted file mode 100644 index fceb54487f..0000000000 --- a/test/files/jvm/t6941/test.scala +++ /dev/null @@ -1,15 +0,0 @@ -import scala.tools.partest.{BytecodeTest, ASMConverters} - -import scala.tools.nsc.util.JavaClassPath -import java.io.InputStream -import scala.tools.asm -import asm.ClassReader -import asm.tree.{ClassNode, InsnList} -import scala.collection.JavaConverters._ - -object Test extends BytecodeTest { - def show: Unit = { - val classNode = loadClassNode("SameBytecode") - similarBytecode(getMethod(classNode, "a"), getMethod(classNode, "b"), ASMConverters.equivalentBytecode(_, _)) - } -} diff --git a/test/files/pos/t2171.flags b/test/files/pos/t2171.flags deleted file mode 100644 index eb4d19bcb9..0000000000 --- a/test/files/pos/t2171.flags +++ /dev/null @@ -1 +0,0 @@ --optimise \ No newline at end of file diff --git a/test/files/pos/t2171.scala b/test/files/pos/t2171.scala deleted file mode 100644 index 6c754c76a6..0000000000 --- a/test/files/pos/t2171.scala +++ /dev/null @@ -1,7 +0,0 @@ -final object test { - def logIgnoredException(msg: => String) = - try 0 catch { case ex => println(msg) } - - def main (args: Array[String]): Unit = - while (true) logIgnoredException ("...") -} diff --git a/test/files/pos/t3252.flags b/test/files/pos/t3252.flags deleted file mode 100644 index eb4d19bcb9..0000000000 --- a/test/files/pos/t3252.flags +++ /dev/null @@ -1 +0,0 @@ --optimise \ No newline at end of file diff --git a/test/files/pos/t3252.scala b/test/files/pos/t3252.scala deleted file mode 100644 index 3ecc1e7cef..0000000000 --- a/test/files/pos/t3252.scala +++ /dev/null @@ -1,15 +0,0 @@ -class A { - def f(x : Boolean) : Thread = { - g { - x match { - case false => - B.h { } - } - } - } - - private def g[T](block : => T) = sys.error("") -} -object B { - def h(block : => Unit) : Nothing = sys.error("") -} diff --git a/test/files/pos/t3420.flags b/test/files/pos/t3420.flags index 4fbafb7e80..397969bb1d 100644 --- a/test/files/pos/t3420.flags +++ b/test/files/pos/t3420.flags @@ -1 +1 @@ --Yopt-warnings Yopt:l:project -Xfatal-warnings \ No newline at end of file +-Yopt-warnings -Yopt:l:classpath -Xfatal-warnings \ No newline at end of file diff --git a/test/files/pos/t3430.flags b/test/files/pos/t3430.flags deleted file mode 100644 index eb4d19bcb9..0000000000 --- a/test/files/pos/t3430.flags +++ /dev/null @@ -1 +0,0 @@ --optimise \ No newline at end of file diff --git a/test/files/pos/t3430.scala b/test/files/pos/t3430.scala deleted file mode 100644 index 3129c6276a..0000000000 --- a/test/files/pos/t3430.scala +++ /dev/null @@ -1,13 +0,0 @@ -// package com.example - -object A { - def f1(f: String => Boolean) = f("a") - - def f2(): Boolean = - f1 { s1 => - f1 { s2 => - while (true) { } - true - } - } -} \ No newline at end of file diff --git a/test/files/pos/t4579.flags b/test/files/pos/t4579.flags deleted file mode 100644 index 1182725e86..0000000000 --- a/test/files/pos/t4579.flags +++ /dev/null @@ -1 +0,0 @@ --optimize \ No newline at end of file diff --git a/test/files/pos/t4579.scala b/test/files/pos/t4579.scala deleted file mode 100644 index cd1553f02a..0000000000 --- a/test/files/pos/t4579.scala +++ /dev/null @@ -1,518 +0,0 @@ -//############################################################################ -// Lisp interpreter (revived as an optimizer test.) -//############################################################################ - -//############################################################################ -// Lisp Scanner - -class LispTokenizer(s: String) extends Iterator[String] { - private var i = 0; - private def isDelimiter(ch: Char) = ch <= ' ' || ch == '(' || ch == ')' - def hasNext: Boolean = { - while (i < s.length() && s.charAt(i) <= ' ') i += 1 - i < s.length() - } - def next: String = - if (hasNext) { - val start = i - if (isDelimiter(s charAt i)) i += 1 - else - do i = i + 1 - while (!isDelimiter(s charAt i)) - s.substring(start, i) - } else sys.error("premature end of string") -} - -//############################################################################ -// Lisp Interface - -trait Lisp { - type Data - - def string2lisp(s: String): Data - def lisp2string(s: Data): String - - def evaluate(d: Data): Data - // !!! def evaluate(s: String): Data = evaluate(string2lisp(s)) - def evaluate(s: String): Data -} - -//############################################################################ -// Lisp Implementation Using Case Classes - -object LispCaseClasses extends Lisp { - - import List.range - - trait Data { - def elemsToString(): String = toString(); - } - case class CONS(car: Data, cdr: Data) extends Data { - override def toString() = "(" + elemsToString() + ")"; - override def elemsToString() = car.toString() + (cdr match { - case NIL() => "" - case _ => " " + cdr.elemsToString(); - }) - } - case class NIL() extends Data { // !!! use case object - override def toString() = "()"; - } - case class SYM(name: String) extends Data { - override def toString() = name; - } - case class NUM(x: Int) extends Data { - override def toString() = x.toString(); - } - case class STR(x: String) extends Data { - override def toString() = "\"" + x + "\""; - } - case class FUN(f: List[Data] => Data) extends Data { - override def toString() = ""; - } - - def list(): Data = - NIL(); - def list(x0: Data): Data = - CONS(x0, NIL()); - def list(x0: Data, x1: Data): Data = - CONS(x0, list(x1)); - def list(x0: Data, x1: Data, x2: Data): Data = - CONS(x0, list(x1, x2)); - def list(x0: Data, x1: Data, x2: Data, x3: Data): Data = - CONS(x0, list(x1, x2, x3)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data): Data = - CONS(x0, list(x1, x2, x3, x4)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data): Data = - CONS(x0, list(x1, x2, x3, x4, x5)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, - x6: Data): Data = - CONS(x0, list(x1, x2, x3, x4, x5, x6)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, - x6: Data, x7: Data): Data = - CONS(x0, list(x1, x2, x3, x4, x5, x6, x7)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, - x6: Data, x7: Data, x8: Data): Data = - CONS(x0, list(x1, x2, x3, x4, x5, x6, x7, x8)); - def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, - x6: Data, x7: Data, x8: Data, x9: Data): Data = - CONS(x0, list(x1, x2, x3, x4, x5, x6, x7, x8, x9)); - - var curexp: Data = null - var trace: Boolean = false - var indent: Int = 0 - - def lispError[a](msg: String): a = - sys.error("error: " + msg + "\n" + curexp); - - trait Environment { - def lookup(n: String): Data; - def extendRec(name: String, expr: Environment => Data) = - new Environment { - def lookup(n: String): Data = - if (n == name) expr(this) else Environment.this.lookup(n); - } - def extend(name: String, v: Data) = extendRec(name, (env1 => v)); - } - val EmptyEnvironment = new Environment { - def lookup(n: String): Data = lispError("undefined: " + n); - } - - def toList(x: Data): List[Data] = x match { - case NIL() => List() - case CONS(y, ys) => y :: toList(ys) - case _ => lispError("malformed list: " + x); - } - - def toBoolean(x: Data) = x match { - case NUM(0) => false - case _ => true - } - - def normalize(x: Data): Data = x match { - case CONS(SYM("def"), - CONS(CONS(SYM(name), args), CONS(body, CONS(expr, NIL())))) => - normalize(list(SYM("def"), - SYM(name), list(SYM("lambda"), args, body), expr)) - case CONS(SYM("cond"), CONS(CONS(SYM("else"), CONS(expr, NIL())),NIL())) => - normalize(expr) - case CONS(SYM("cond"), CONS(CONS(test, CONS(expr, NIL())), rest)) => - normalize(list(SYM("if"), test, expr, CONS(SYM("cond"), rest))) - case CONS(h, t) => CONS(normalize(h), normalize(t)) - case _ => x - } - - def eval(x: Data, env: Environment): Data = { - val prevexp = curexp; - curexp = x; - if (trace) { - for (x <- range(1, indent)) Console.print(" "); - Console.println("===> " + x); - indent = indent + 1; - } - val result = eval1(x, env); - if (trace) { - indent = indent - 1; - for (x <- range(1, indent)) Console.print(" "); - Console.println("<=== " + result); - } - curexp = prevexp; - result - } - - def eval1(x: Data, env: Environment): Data = x match { - case SYM(name) => - env lookup name - case CONS(SYM("def"), CONS(SYM(name), CONS(y, CONS(z, NIL())))) => - eval(z, env.extendRec(name, (env1 => eval(y, env1)))) - case CONS(SYM("val"), CONS(SYM(name), CONS(y, CONS(z, NIL())))) => - eval(z, env.extend(name, eval(y, env))) - case CONS(SYM("lambda"), CONS(params, CONS(y, NIL()))) => - mkLambda(params, y, env) - case CONS(SYM("if"), CONS(c, CONS(t, CONS(e, NIL())))) => - if (toBoolean(eval(c, env))) eval(t, env) else eval(e, env) - case CONS(SYM("quote"), CONS(x, NIL())) => - x - case CONS(y, xs) => - apply(eval(y, env), toList(xs) map (x => eval(x, env))) - case NUM(_) => x - case STR(_) => x - case FUN(_) => x - case _ => - lispError("illegal term") - } - - def apply(fn: Data, args: List[Data]): Data = fn match { - case FUN(f) => f(args); - case _ => lispError("application of non-function: " + fn); - } - - def mkLambda(params: Data, expr: Data, env: Environment): Data = { - - def extendEnv(env: Environment, - ps: List[String], args: List[Data]): Environment = - (ps, args) match { - case (List(), List()) => - env - case (p :: ps1, arg :: args1) => - extendEnv(env.extend(p, arg), ps1, args1) - case _ => - lispError("wrong number of arguments") - } - - val ps: List[String] = toList(params) map { - case SYM(name) => name - case _ => sys.error("illegal parameter list"); - } - - FUN(args => eval(expr, extendEnv(env, ps, args))) - } - - val globalEnv = EmptyEnvironment - .extend("=", FUN({ - case List(NUM(arg1),NUM(arg2)) => NUM(if (arg1 == arg2) 1 else 0) - case List(STR(arg1),STR(arg2)) => NUM(if (arg1 == arg2) 1 else 0)})) - .extend("+", FUN({ - case List(NUM(arg1),NUM(arg2)) => NUM(arg1 + arg2) - case List(STR(arg1),STR(arg2)) => STR(arg1 + arg2)})) - .extend("-", FUN({ - case List(NUM(arg1),NUM(arg2)) => NUM(arg1 - arg2)})) - .extend("*", FUN({ - case List(NUM(arg1),NUM(arg2)) => NUM(arg1 * arg2)})) - .extend("/", FUN({ - case List(NUM(arg1),NUM(arg2)) => NUM(arg1 / arg2)})) - .extend("car", FUN({ - case List(CONS(x, xs)) => x})) - .extend("cdr", FUN({ - case List(CONS(x, xs)) => xs})) - .extend("null?", FUN({ - case List(NIL()) => NUM(1) - case _ => NUM(0)})) - .extend("cons", FUN({ - case List(x, y) => CONS(x, y)})); - - def evaluate(x: Data): Data = eval(normalize(x), globalEnv); - def evaluate(s: String): Data = evaluate(string2lisp(s)); - - def string2lisp(s: String): Data = { - val it = new LispTokenizer(s); - def parse(token: String): Data = { - if (token == "(") parseList - else if (token == ")") sys.error("unbalanced parentheses") - else if ('0' <= token.charAt(0) && token.charAt(0) <= '9') - NUM(token.toInt) - else if (token.charAt(0) == '\"' && token.charAt(token.length()-1)=='\"') - STR(token.substring(1,token.length() - 1)) - else SYM(token) - } - def parseList: Data = { - val token = it.next; - if (token == ")") NIL() else CONS(parse(token), parseList) - } - parse(it.next) - } - - def lisp2string(d: Data): String = d.toString(); -} - -//############################################################################ -// Lisp Implementation Using Any - -object LispAny extends Lisp { - - import List._; - - type Data = Any; - - case class Lambda(f: List[Data] => Data); - - var curexp: Data = null; - var trace: Boolean = false; - var indent: Int = 0; - - def lispError[a](msg: String): a = - sys.error("error: " + msg + "\n" + curexp); - - trait Environment { - def lookup(n: String): Data; - def extendRec(name: String, expr: Environment => Data) = - new Environment { - def lookup(n: String): Data = - if (n == name) expr(this) else Environment.this.lookup(n); - } - def extend(name: String, v: Data) = extendRec(name, (env1 => v)); - } - val EmptyEnvironment = new Environment { - def lookup(n: String): Data = lispError("undefined: " + n); - } - - def asList(x: Data): List[Data] = x match { - case y: List[_] => y - case _ => lispError("malformed list: " + x) - } - - def asInt(x: Data): Int = x match { - case y: Int => y - case _ => lispError("not an integer: " + x) - } - - def asString(x: Data): String = x match { - case y: String => y - case _ => lispError("not a string: " + x) - } - - def asBoolean(x: Data): Boolean = x != 0 - - def normalize(x: Data): Data = x match { - case 'and :: x :: y :: Nil => - normalize('if :: x :: y :: 0 :: Nil) - case 'or :: x :: y :: Nil => - normalize('if :: x :: 1 :: y :: Nil) - case 'def :: (name :: args) :: body :: expr :: Nil => - normalize('def :: name :: ('lambda :: args :: body :: Nil) :: expr :: Nil) - case 'cond :: ('else :: expr :: Nil) :: rest => - normalize(expr); - case 'cond :: (test :: expr :: Nil) :: rest => - normalize('if :: test :: expr :: ('cond :: rest) :: Nil) - case 'cond :: 'else :: expr :: Nil => - normalize(expr) - case h :: t => - normalize(h) :: asList(normalize(t)) - case _ => - x - } - - def eval(x: Data, env: Environment): Data = { - val prevexp = curexp; - curexp = x; - if (trace) { - for (x <- range(1, indent)) Console.print(" "); - Console.println("===> " + x); - indent += 1; - } - val result = eval1(x, env); - if (trace) { - indent -= 1; - for (x <- range(1, indent)) Console.print(" "); - Console.println("<=== " + result); - } - curexp = prevexp; - result - } - - def eval1(x: Data, env: Environment): Data = x match { - case Symbol(name) => - env lookup name - case 'def :: Symbol(name) :: y :: z :: Nil => - eval(z, env.extendRec(name, (env1 => eval(y, env1)))) - case 'val :: Symbol(name) :: y :: z :: Nil => - eval(z, env.extend(name, eval(y, env))) - case 'lambda :: params :: y :: Nil => - mkLambda(params, y, env) - case 'if :: c :: y :: z :: Nil => - if (asBoolean(eval(c, env))) eval(y, env) else eval(z, env) - case 'quote :: y :: Nil => - y - case y :: z => - apply(eval(y, env), z map (x => eval(x, env))) - case Lambda(_) => x - case y: String => x - case y: Int => x - case y => lispError("illegal term") - } - - def lisp2string(x: Data): String = x match { - case Symbol(name) => name - case Nil => "()" - case y :: ys => - def list2string(xs: List[Data]): String = xs match { - case List() => "" - case y :: ys => " " + lisp2string(y) + list2string(ys) - } - "(" + lisp2string(y) + list2string(ys) + ")" - case _ => if (x.isInstanceOf[String]) "\"" + x + "\""; else x.toString() - } - - def apply(fn: Data, args: List[Data]): Data = fn match { - case Lambda(f) => f(args); - case _ => lispError("application of non-function: " + fn + " to " + args); - } - - def mkLambda(params: Data, expr: Data, env: Environment): Data = { - - def extendEnv(env: Environment, - ps: List[String], args: List[Data]): Environment = - (ps, args) match { - case (List(), List()) => - env - case (p :: ps1, arg :: args1) => - extendEnv(env.extend(p, arg), ps1, args1) - case _ => - lispError("wrong number of arguments") - } - - val ps: List[String] = asList(params) map { - case Symbol(name) => name - case _ => sys.error("illegal parameter list"); - } - - Lambda(args => eval(expr, extendEnv(env, ps, args))) - } - - val globalEnv = EmptyEnvironment - .extend("=", Lambda{ - case List(arg1, arg2) => if(arg1 == arg2) 1 else 0}) - .extend("+", Lambda{ - case List(arg1: Int, arg2: Int) => arg1 + arg2 - case List(arg1: String, arg2: String) => arg1 + arg2}) - .extend("-", Lambda{ - case List(arg1: Int, arg2: Int) => arg1 - arg2}) - .extend("*", Lambda{ - case List(arg1: Int, arg2: Int) => arg1 * arg2}) - .extend("/", Lambda{ - case List(arg1: Int, arg2: Int) => arg1 / arg2}) - .extend("nil", Nil) - .extend("cons", Lambda{ - case List(arg1, arg2) => arg1 :: asList(arg2)}) - .extend("car", Lambda{ - case List(x :: xs) => x}) - .extend("cdr", Lambda{ - case List(x :: xs) => xs}) - .extend("null?", Lambda{ - case List(Nil) => 1 - case _ => 0}); - - def evaluate(x: Data): Data = eval(normalize(x), globalEnv); - def evaluate(s: String): Data = evaluate(string2lisp(s)); - - def string2lisp(s: String): Data = { - val it = new LispTokenizer(s); - def parse(token: String): Data = { - if (token == "(") parseList - else if (token == ")") sys.error("unbalanced parentheses") - //else if (Character.isDigit(token.charAt(0))) - else if (token.charAt(0).isDigit) - token.toInt - else if (token.charAt(0) == '\"' && token.charAt(token.length()-1)=='\"') - token.substring(1,token.length() - 1) - else Symbol(token) - } - def parseList: List[Data] = { - val token = it.next; - if (token == ")") Nil else parse(token) :: parseList - } - parse(it.next) - } -} - -//############################################################################ -// List User - -class LispUser(lisp: Lisp) { - - import lisp._; - - def evaluate(s: String) = lisp2string(lisp.evaluate(s)); - - def run = { - - Console.println(string2lisp("(lambda (x) (+ (* x x) 1))").asInstanceOf[AnyRef]); - Console.println(lisp2string(string2lisp("(lambda (x) (+ (* x x) 1))"))); - Console.println; - - Console.println("( '(1 2 3)) = " + evaluate(" (quote(1 2 3))")); - Console.println("(car '(1 2 3)) = " + evaluate("(car (quote(1 2 3)))")); - Console.println("(cdr '(1 2 3)) = " + evaluate("(cdr (quote(1 2 3)))")); - Console.println("(null? '(2 3)) = " + evaluate("(null? (quote(2 3)))")); - Console.println("(null? '()) = " + evaluate("(null? (quote()))")); - Console.println; - - Console.println("faculty(10) = " + evaluate( - "(def (faculty n) " + - "(if (= n 0) " + - "1 " + - "(* n (faculty (- n 1)))) " + - "(faculty 10))")); - Console.println("faculty(10) = " + evaluate( - "(def (faculty n) " + - "(cond " + - "((= n 0) 1) " + - "(else (* n (faculty (- n 1))))) " + - "(faculty 10))")); - Console.println("foobar = " + evaluate( - "(def (foo n) " + - "(cond " + - "((= n 0) \"a\")" + - "((= n 1) \"b\")" + - "((= (/ n 2) 1) " + - "(cond " + - "((= n 2) \"c\")" + - "(else \"d\")))" + - "(else " + - "(def (bar m) " + - "(cond " + - "((= m 0) \"e\")" + - "((= m 1) \"f\")" + - "(else \"z\"))" + - "(bar (- n 4)))))" + - "(val nil (quote ())" + - "(val v1 (foo 0) " + - "(val v2 (+ (foo 1) (foo 2)) " + - "(val v3 (+ (+ (foo 3) (foo 4)) (foo 5)) " + - "(val v4 (foo 6) " + - "(cons v1 (cons v2 (cons v3 (cons v4 nil))))))))))")); - Console.println; - } -} - -//############################################################################ -// Main - -object Test { - def main(args: Array[String]) { - new LispUser(LispCaseClasses).run; - new LispUser(LispAny).run; - () - } -} - -//############################################################################ diff --git a/test/files/pos/t4840.flags b/test/files/pos/t4840.flags index eb4d19bcb9..422d6be431 100644 --- a/test/files/pos/t4840.flags +++ b/test/files/pos/t4840.flags @@ -1 +1 @@ --optimise \ No newline at end of file +-Yopt:l:classpath \ No newline at end of file diff --git a/test/files/pos/t6157.flags b/test/files/pos/t6157.flags deleted file mode 100644 index 0ebca3e7af..0000000000 --- a/test/files/pos/t6157.flags +++ /dev/null @@ -1 +0,0 @@ - -optimize diff --git a/test/files/pos/t6157.scala b/test/files/pos/t6157.scala deleted file mode 100644 index 7463989b14..0000000000 --- a/test/files/pos/t6157.scala +++ /dev/null @@ -1,25 +0,0 @@ -// SI-6157 - Compiler crash on inlined function and -optimize option - -object Test { - def main(args: Array[String]) { - Console.println( - ErrorHandler.defaultIfIOException("String")("String") - ) - } -} - -import java.io.IOException - -object ErrorHandler { - - @inline - def defaultIfIOException[T](default: => T)(closure: => T): T = { - try { - closure - } catch { - case e: IOException => - default - } - } -} - diff --git a/test/files/pos/t6547.flags b/test/files/pos/t6547.flags deleted file mode 100644 index c9b68d70dc..0000000000 --- a/test/files/pos/t6547.flags +++ /dev/null @@ -1 +0,0 @@ --optimise diff --git a/test/files/pos/t6547.scala b/test/files/pos/t6547.scala deleted file mode 100644 index 53bd798219..0000000000 --- a/test/files/pos/t6547.scala +++ /dev/null @@ -1,6 +0,0 @@ -trait ConfigurableDefault[@specialized V] { - def fillArray(arr: Array[V], v: V) = (arr: Any) match { - case x: Array[Int] => null - case x: Array[Long] => v.asInstanceOf[Long] - } -} diff --git a/test/files/pos/t8062.flags b/test/files/pos/t8062.flags deleted file mode 100644 index 49d036a887..0000000000 --- a/test/files/pos/t8062.flags +++ /dev/null @@ -1 +0,0 @@ --optimize diff --git a/test/files/pos/t8062/A_1.scala b/test/files/pos/t8062/A_1.scala deleted file mode 100644 index ca0411dae8..0000000000 --- a/test/files/pos/t8062/A_1.scala +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index f0a6761488..0000000000 --- a/test/files/pos/t8062/B_2.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Test { - warmup.Warmup.filter[Any](x => false) -} diff --git a/test/files/pos/t8306.flags b/test/files/pos/t8306.flags deleted file mode 100644 index 49d036a887..0000000000 --- a/test/files/pos/t8306.flags +++ /dev/null @@ -1 +0,0 @@ --optimize diff --git a/test/files/pos/t8306.scala b/test/files/pos/t8306.scala deleted file mode 100644 index e04b054eb9..0000000000 --- a/test/files/pos/t8306.scala +++ /dev/null @@ -1,8 +0,0 @@ -class Si8306 { - def foo: Int = 123 - lazy val extension: Int = - foo match { - case idx if idx != -1 => 15 - case _ => 17 - } -} diff --git a/test/files/pos/t8359-closelim-crash.flags b/test/files/pos/t8359-closelim-crash.flags deleted file mode 100644 index 49d036a887..0000000000 --- a/test/files/pos/t8359-closelim-crash.flags +++ /dev/null @@ -1 +0,0 @@ --optimize diff --git a/test/files/pos/t8359-closelim-crash.scala b/test/files/pos/t8359-closelim-crash.scala deleted file mode 100644 index 1413694d10..0000000000 --- a/test/files/pos/t8359-closelim-crash.scala +++ /dev/null @@ -1,23 +0,0 @@ -package test - -// This is a minimization of code that crashed the compiler during bootstrapping -// in the first iteration of https://github.com/scala/scala/pull/4373, the PR -// that adjusted the order of free and declared params in LambdaLift. - -// Was: -// java.lang.AssertionError: assertion failed: -// Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1 -// at scala.tools.nsc.Global.assert(Global.scala:262) -// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113) -// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122) -// at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124) -class Typer { - def bar(a: Boolean, b: Boolean): Unit = { - @inline - def baz(): Unit = { - ((_: Any) => (Typer.this, a, b)).apply("") - } - ((_: Any) => baz()).apply("") - } -} - diff --git a/test/files/pos/t9123.flags b/test/files/pos/t9123.flags deleted file mode 100644 index c16e2f71dc..0000000000 --- a/test/files/pos/t9123.flags +++ /dev/null @@ -1 +0,0 @@ --optimize -Ydelambdafy:method diff --git a/test/files/pos/t9123.scala b/test/files/pos/t9123.scala deleted file mode 100644 index 22d55b4351..0000000000 --- a/test/files/pos/t9123.scala +++ /dev/null @@ -1,10 +0,0 @@ -trait Setting { - type T - def value: T -} - -object Test { - def test(x: Some[Setting]) = x match { - case Some(dep) => Some(dep.value) map (_ => true) - } -} diff --git a/test/files/pos/trait-force-info.flags b/test/files/pos/trait-force-info.flags deleted file mode 100644 index eb4d19bcb9..0000000000 --- a/test/files/pos/trait-force-info.flags +++ /dev/null @@ -1 +0,0 @@ --optimise \ No newline at end of file diff --git a/test/files/pos/trait-force-info.scala b/test/files/pos/trait-force-info.scala deleted file mode 100644 index c2b33869c3..0000000000 --- a/test/files/pos/trait-force-info.scala +++ /dev/null @@ -1,18 +0,0 @@ -/** This does NOT crash unless it's in the interactive package. - */ - -package scala.tools.nsc -package interactive - -trait MyContextTrees { - val self: Global - val NoContext = self.analyzer.NoContext -} -// -// error: java.lang.AssertionError: assertion failed: trait Contexts.NoContext$ linkedModule: List() -// at scala.Predef$.assert(Predef.scala:160) -// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.innerSymbol$1(ClassfileParser.scala:1211) -// at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.classSymbol(ClassfileParser.scala:1223) -// at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:489) -// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:757) -// at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:789) diff --git a/test/files/run/elidable-opt.scala b/test/files/run/elidable-opt.scala index ebada46de8..a2f29d2caf 100644 --- a/test/files/run/elidable-opt.scala +++ b/test/files/run/elidable-opt.scala @@ -1,6 +1,3 @@ -/* - * filter: inliner warnings; re-run with - */ import annotation._ import elidable._ diff --git a/test/files/run/lisp.check b/test/files/run/lisp.check new file mode 100644 index 0000000000..64053f26d0 --- /dev/null +++ b/test/files/run/lisp.check @@ -0,0 +1,26 @@ +(lambda (x) (+ (* x x) 1)) +(lambda (x) (+ (* x x) 1)) + +( '(1 2 3)) = (1 2 3) +(car '(1 2 3)) = 1 +(cdr '(1 2 3)) = (2 3) +(null? '(2 3)) = 0 +(null? '()) = 1 + +faculty(10) = 3628800 +faculty(10) = 3628800 +foobar = ("a" "bc" "def" "z") + +List('lambda, List('x), List('+, List('*, 'x, 'x), 1)) +(lambda (x) (+ (* x x) 1)) + +( '(1 2 3)) = (1 2 3) +(car '(1 2 3)) = 1 +(cdr '(1 2 3)) = (2 3) +(null? '(2 3)) = 0 +(null? '()) = 1 + +faculty(10) = 3628800 +faculty(10) = 3628800 +foobar = ("a" "bc" "def" "z") + diff --git a/test/files/run/lisp.scala b/test/files/run/lisp.scala new file mode 100644 index 0000000000..162c7d2599 --- /dev/null +++ b/test/files/run/lisp.scala @@ -0,0 +1,518 @@ +//############################################################################ +// Lisp interpreter +//############################################################################ + +//############################################################################ +// Lisp Scanner + +class LispTokenizer(s: String) extends Iterator[String] { + private var i = 0; + private def isDelimiter(ch: Char) = ch <= ' ' || ch == '(' || ch == ')' + def hasNext: Boolean = { + while (i < s.length() && s.charAt(i) <= ' ') i += 1 + i < s.length() + } + def next: String = + if (hasNext) { + val start = i + if (isDelimiter(s charAt i)) i += 1 + else + do i = i + 1 + while (!isDelimiter(s charAt i)) + s.substring(start, i) + } else sys.error("premature end of string") +} + +//############################################################################ +// Lisp Interface + +trait Lisp { + type Data + + def string2lisp(s: String): Data + def lisp2string(s: Data): String + + def evaluate(d: Data): Data + // !!! def evaluate(s: String): Data = evaluate(string2lisp(s)) + def evaluate(s: String): Data +} + +//############################################################################ +// Lisp Implementation Using Case Classes + +object LispCaseClasses extends Lisp { + + import List.range + + trait Data { + def elemsToString(): String = toString(); + } + case class CONS(car: Data, cdr: Data) extends Data { + override def toString() = "(" + elemsToString() + ")"; + override def elemsToString() = car.toString() + (cdr match { + case NIL() => "" + case _ => " " + cdr.elemsToString(); + }) + } + case class NIL() extends Data { // !!! use case object + override def toString() = "()"; + } + case class SYM(name: String) extends Data { + override def toString() = name; + } + case class NUM(x: Int) extends Data { + override def toString() = x.toString(); + } + case class STR(x: String) extends Data { + override def toString() = "\"" + x + "\""; + } + case class FUN(f: List[Data] => Data) extends Data { + override def toString() = ""; + } + + def list(): Data = + NIL(); + def list(x0: Data): Data = + CONS(x0, NIL()); + def list(x0: Data, x1: Data): Data = + CONS(x0, list(x1)); + def list(x0: Data, x1: Data, x2: Data): Data = + CONS(x0, list(x1, x2)); + def list(x0: Data, x1: Data, x2: Data, x3: Data): Data = + CONS(x0, list(x1, x2, x3)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data): Data = + CONS(x0, list(x1, x2, x3, x4)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data): Data = + CONS(x0, list(x1, x2, x3, x4, x5)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, + x6: Data): Data = + CONS(x0, list(x1, x2, x3, x4, x5, x6)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, + x6: Data, x7: Data): Data = + CONS(x0, list(x1, x2, x3, x4, x5, x6, x7)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, + x6: Data, x7: Data, x8: Data): Data = + CONS(x0, list(x1, x2, x3, x4, x5, x6, x7, x8)); + def list(x0: Data, x1: Data, x2: Data, x3: Data, x4: Data, x5: Data, + x6: Data, x7: Data, x8: Data, x9: Data): Data = + CONS(x0, list(x1, x2, x3, x4, x5, x6, x7, x8, x9)); + + var curexp: Data = null + var trace: Boolean = false + var indent: Int = 0 + + def lispError[a](msg: String): a = + sys.error("error: " + msg + "\n" + curexp); + + trait Environment { + def lookup(n: String): Data; + def extendRec(name: String, expr: Environment => Data) = + new Environment { + def lookup(n: String): Data = + if (n == name) expr(this) else Environment.this.lookup(n); + } + def extend(name: String, v: Data) = extendRec(name, (env1 => v)); + } + val EmptyEnvironment = new Environment { + def lookup(n: String): Data = lispError("undefined: " + n); + } + + def toList(x: Data): List[Data] = x match { + case NIL() => List() + case CONS(y, ys) => y :: toList(ys) + case _ => lispError("malformed list: " + x); + } + + def toBoolean(x: Data) = x match { + case NUM(0) => false + case _ => true + } + + def normalize(x: Data): Data = x match { + case CONS(SYM("def"), + CONS(CONS(SYM(name), args), CONS(body, CONS(expr, NIL())))) => + normalize(list(SYM("def"), + SYM(name), list(SYM("lambda"), args, body), expr)) + case CONS(SYM("cond"), CONS(CONS(SYM("else"), CONS(expr, NIL())),NIL())) => + normalize(expr) + case CONS(SYM("cond"), CONS(CONS(test, CONS(expr, NIL())), rest)) => + normalize(list(SYM("if"), test, expr, CONS(SYM("cond"), rest))) + case CONS(h, t) => CONS(normalize(h), normalize(t)) + case _ => x + } + + def eval(x: Data, env: Environment): Data = { + val prevexp = curexp; + curexp = x; + if (trace) { + for (x <- range(1, indent)) Console.print(" "); + Console.println("===> " + x); + indent = indent + 1; + } + val result = eval1(x, env); + if (trace) { + indent = indent - 1; + for (x <- range(1, indent)) Console.print(" "); + Console.println("<=== " + result); + } + curexp = prevexp; + result + } + + def eval1(x: Data, env: Environment): Data = x match { + case SYM(name) => + env lookup name + case CONS(SYM("def"), CONS(SYM(name), CONS(y, CONS(z, NIL())))) => + eval(z, env.extendRec(name, (env1 => eval(y, env1)))) + case CONS(SYM("val"), CONS(SYM(name), CONS(y, CONS(z, NIL())))) => + eval(z, env.extend(name, eval(y, env))) + case CONS(SYM("lambda"), CONS(params, CONS(y, NIL()))) => + mkLambda(params, y, env) + case CONS(SYM("if"), CONS(c, CONS(t, CONS(e, NIL())))) => + if (toBoolean(eval(c, env))) eval(t, env) else eval(e, env) + case CONS(SYM("quote"), CONS(x, NIL())) => + x + case CONS(y, xs) => + apply(eval(y, env), toList(xs) map (x => eval(x, env))) + case NUM(_) => x + case STR(_) => x + case FUN(_) => x + case _ => + lispError("illegal term") + } + + def apply(fn: Data, args: List[Data]): Data = fn match { + case FUN(f) => f(args); + case _ => lispError("application of non-function: " + fn); + } + + def mkLambda(params: Data, expr: Data, env: Environment): Data = { + + def extendEnv(env: Environment, + ps: List[String], args: List[Data]): Environment = + (ps, args) match { + case (List(), List()) => + env + case (p :: ps1, arg :: args1) => + extendEnv(env.extend(p, arg), ps1, args1) + case _ => + lispError("wrong number of arguments") + } + + val ps: List[String] = toList(params) map { + case SYM(name) => name + case _ => sys.error("illegal parameter list"); + } + + FUN(args => eval(expr, extendEnv(env, ps, args))) + } + + val globalEnv = EmptyEnvironment + .extend("=", FUN({ + case List(NUM(arg1),NUM(arg2)) => NUM(if (arg1 == arg2) 1 else 0) + case List(STR(arg1),STR(arg2)) => NUM(if (arg1 == arg2) 1 else 0)})) + .extend("+", FUN({ + case List(NUM(arg1),NUM(arg2)) => NUM(arg1 + arg2) + case List(STR(arg1),STR(arg2)) => STR(arg1 + arg2)})) + .extend("-", FUN({ + case List(NUM(arg1),NUM(arg2)) => NUM(arg1 - arg2)})) + .extend("*", FUN({ + case List(NUM(arg1),NUM(arg2)) => NUM(arg1 * arg2)})) + .extend("/", FUN({ + case List(NUM(arg1),NUM(arg2)) => NUM(arg1 / arg2)})) + .extend("car", FUN({ + case List(CONS(x, xs)) => x})) + .extend("cdr", FUN({ + case List(CONS(x, xs)) => xs})) + .extend("null?", FUN({ + case List(NIL()) => NUM(1) + case _ => NUM(0)})) + .extend("cons", FUN({ + case List(x, y) => CONS(x, y)})); + + def evaluate(x: Data): Data = eval(normalize(x), globalEnv); + def evaluate(s: String): Data = evaluate(string2lisp(s)); + + def string2lisp(s: String): Data = { + val it = new LispTokenizer(s); + def parse(token: String): Data = { + if (token == "(") parseList + else if (token == ")") sys.error("unbalanced parentheses") + else if ('0' <= token.charAt(0) && token.charAt(0) <= '9') + NUM(token.toInt) + else if (token.charAt(0) == '\"' && token.charAt(token.length()-1)=='\"') + STR(token.substring(1,token.length() - 1)) + else SYM(token) + } + def parseList: Data = { + val token = it.next; + if (token == ")") NIL() else CONS(parse(token), parseList) + } + parse(it.next) + } + + def lisp2string(d: Data): String = d.toString(); +} + +//############################################################################ +// Lisp Implementation Using Any + +object LispAny extends Lisp { + + import List._; + + type Data = Any; + + case class Lambda(f: List[Data] => Data); + + var curexp: Data = null; + var trace: Boolean = false; + var indent: Int = 0; + + def lispError[a](msg: String): a = + sys.error("error: " + msg + "\n" + curexp); + + trait Environment { + def lookup(n: String): Data; + def extendRec(name: String, expr: Environment => Data) = + new Environment { + def lookup(n: String): Data = + if (n == name) expr(this) else Environment.this.lookup(n); + } + def extend(name: String, v: Data) = extendRec(name, (env1 => v)); + } + val EmptyEnvironment = new Environment { + def lookup(n: String): Data = lispError("undefined: " + n); + } + + def asList(x: Data): List[Data] = x match { + case y: List[_] => y + case _ => lispError("malformed list: " + x) + } + + def asInt(x: Data): Int = x match { + case y: Int => y + case _ => lispError("not an integer: " + x) + } + + def asString(x: Data): String = x match { + case y: String => y + case _ => lispError("not a string: " + x) + } + + def asBoolean(x: Data): Boolean = x != 0 + + def normalize(x: Data): Data = x match { + case 'and :: x :: y :: Nil => + normalize('if :: x :: y :: 0 :: Nil) + case 'or :: x :: y :: Nil => + normalize('if :: x :: 1 :: y :: Nil) + case 'def :: (name :: args) :: body :: expr :: Nil => + normalize('def :: name :: ('lambda :: args :: body :: Nil) :: expr :: Nil) + case 'cond :: ('else :: expr :: Nil) :: rest => + normalize(expr); + case 'cond :: (test :: expr :: Nil) :: rest => + normalize('if :: test :: expr :: ('cond :: rest) :: Nil) + case 'cond :: 'else :: expr :: Nil => + normalize(expr) + case h :: t => + normalize(h) :: asList(normalize(t)) + case _ => + x + } + + def eval(x: Data, env: Environment): Data = { + val prevexp = curexp; + curexp = x; + if (trace) { + for (x <- range(1, indent)) Console.print(" "); + Console.println("===> " + x); + indent += 1; + } + val result = eval1(x, env); + if (trace) { + indent -= 1; + for (x <- range(1, indent)) Console.print(" "); + Console.println("<=== " + result); + } + curexp = prevexp; + result + } + + def eval1(x: Data, env: Environment): Data = x match { + case Symbol(name) => + env lookup name + case 'def :: Symbol(name) :: y :: z :: Nil => + eval(z, env.extendRec(name, (env1 => eval(y, env1)))) + case 'val :: Symbol(name) :: y :: z :: Nil => + eval(z, env.extend(name, eval(y, env))) + case 'lambda :: params :: y :: Nil => + mkLambda(params, y, env) + case 'if :: c :: y :: z :: Nil => + if (asBoolean(eval(c, env))) eval(y, env) else eval(z, env) + case 'quote :: y :: Nil => + y + case y :: z => + apply(eval(y, env), z map (x => eval(x, env))) + case Lambda(_) => x + case y: String => x + case y: Int => x + case y => lispError("illegal term") + } + + def lisp2string(x: Data): String = x match { + case Symbol(name) => name + case Nil => "()" + case y :: ys => + def list2string(xs: List[Data]): String = xs match { + case List() => "" + case y :: ys => " " + lisp2string(y) + list2string(ys) + } + "(" + lisp2string(y) + list2string(ys) + ")" + case _ => if (x.isInstanceOf[String]) "\"" + x + "\""; else x.toString() + } + + def apply(fn: Data, args: List[Data]): Data = fn match { + case Lambda(f) => f(args); + case _ => lispError("application of non-function: " + fn + " to " + args); + } + + def mkLambda(params: Data, expr: Data, env: Environment): Data = { + + def extendEnv(env: Environment, + ps: List[String], args: List[Data]): Environment = + (ps, args) match { + case (List(), List()) => + env + case (p :: ps1, arg :: args1) => + extendEnv(env.extend(p, arg), ps1, args1) + case _ => + lispError("wrong number of arguments") + } + + val ps: List[String] = asList(params) map { + case Symbol(name) => name + case _ => sys.error("illegal parameter list"); + } + + Lambda(args => eval(expr, extendEnv(env, ps, args))) + } + + val globalEnv = EmptyEnvironment + .extend("=", Lambda{ + case List(arg1, arg2) => if(arg1 == arg2) 1 else 0}) + .extend("+", Lambda{ + case List(arg1: Int, arg2: Int) => arg1 + arg2 + case List(arg1: String, arg2: String) => arg1 + arg2}) + .extend("-", Lambda{ + case List(arg1: Int, arg2: Int) => arg1 - arg2}) + .extend("*", Lambda{ + case List(arg1: Int, arg2: Int) => arg1 * arg2}) + .extend("/", Lambda{ + case List(arg1: Int, arg2: Int) => arg1 / arg2}) + .extend("nil", Nil) + .extend("cons", Lambda{ + case List(arg1, arg2) => arg1 :: asList(arg2)}) + .extend("car", Lambda{ + case List(x :: xs) => x}) + .extend("cdr", Lambda{ + case List(x :: xs) => xs}) + .extend("null?", Lambda{ + case List(Nil) => 1 + case _ => 0}); + + def evaluate(x: Data): Data = eval(normalize(x), globalEnv); + def evaluate(s: String): Data = evaluate(string2lisp(s)); + + def string2lisp(s: String): Data = { + val it = new LispTokenizer(s); + def parse(token: String): Data = { + if (token == "(") parseList + else if (token == ")") sys.error("unbalanced parentheses") + //else if (Character.isDigit(token.charAt(0))) + else if (token.charAt(0).isDigit) + token.toInt + else if (token.charAt(0) == '\"' && token.charAt(token.length()-1)=='\"') + token.substring(1,token.length() - 1) + else Symbol(token) + } + def parseList: List[Data] = { + val token = it.next; + if (token == ")") Nil else parse(token) :: parseList + } + parse(it.next) + } +} + +//############################################################################ +// List User + +class LispUser(lisp: Lisp) { + + import lisp._; + + def evaluate(s: String) = lisp2string(lisp.evaluate(s)); + + def run = { + + Console.println(string2lisp("(lambda (x) (+ (* x x) 1))").asInstanceOf[AnyRef]); + Console.println(lisp2string(string2lisp("(lambda (x) (+ (* x x) 1))"))); + Console.println; + + Console.println("( '(1 2 3)) = " + evaluate(" (quote(1 2 3))")); + Console.println("(car '(1 2 3)) = " + evaluate("(car (quote(1 2 3)))")); + Console.println("(cdr '(1 2 3)) = " + evaluate("(cdr (quote(1 2 3)))")); + Console.println("(null? '(2 3)) = " + evaluate("(null? (quote(2 3)))")); + Console.println("(null? '()) = " + evaluate("(null? (quote()))")); + Console.println; + + Console.println("faculty(10) = " + evaluate( + "(def (faculty n) " + + "(if (= n 0) " + + "1 " + + "(* n (faculty (- n 1)))) " + + "(faculty 10))")); + Console.println("faculty(10) = " + evaluate( + "(def (faculty n) " + + "(cond " + + "((= n 0) 1) " + + "(else (* n (faculty (- n 1))))) " + + "(faculty 10))")); + Console.println("foobar = " + evaluate( + "(def (foo n) " + + "(cond " + + "((= n 0) \"a\")" + + "((= n 1) \"b\")" + + "((= (/ n 2) 1) " + + "(cond " + + "((= n 2) \"c\")" + + "(else \"d\")))" + + "(else " + + "(def (bar m) " + + "(cond " + + "((= m 0) \"e\")" + + "((= m 1) \"f\")" + + "(else \"z\"))" + + "(bar (- n 4)))))" + + "(val nil (quote ())" + + "(val v1 (foo 0) " + + "(val v2 (+ (foo 1) (foo 2)) " + + "(val v3 (+ (+ (foo 3) (foo 4)) (foo 5)) " + + "(val v4 (foo 6) " + + "(cons v1 (cons v2 (cons v3 (cons v4 nil))))))))))")); + Console.println; + } +} + +//############################################################################ +// Main + +object Test { + def main(args: Array[String]) { + new LispUser(LispCaseClasses).run; + new LispUser(LispAny).run; + () + } +} + +//############################################################################ diff --git a/test/files/run/t7008-scala-defined.flags b/test/files/run/t7008-scala-defined.flags deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/files/run/t7008-scala-defined/Test_3.scala b/test/files/run/t7008-scala-defined/Test_3.scala index 26178142ab..ee7b9d9cde 100644 --- a/test/files/run/t7008-scala-defined/Test_3.scala +++ b/test/files/run/t7008-scala-defined/Test_3.scala @@ -1,6 +1,3 @@ -/* - * filter: inliner warning; re-run with - */ import scala.reflect.runtime.universe._ object Test extends App { diff --git a/test/files/run/t7582.check b/test/files/run/t7582.check index 0cfbf08886..58d0f19f5d 100644 --- a/test/files/run/t7582.check +++ b/test/files/run/t7582.check @@ -1 +1,6 @@ +InlineHolder.scala:9: warning: p1/InlineHolder$::inlinable()I is annotated @inline but could not be inlined: +The callee p1/InlineHolder$::inlinable()I contains the instruction INVOKESTATIC p1/PackageProtectedJava.protectedMethod ()I +that would cause an IllegalAccessError when inlined into class O$. + def x = p1.InlineHolder.inlinable + ^ 2 diff --git a/test/files/run/t7582.flags b/test/files/run/t7582.flags index 422d6be431..1f45833eff 100644 --- a/test/files/run/t7582.flags +++ b/test/files/run/t7582.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-Yopt:l:classpath -Yopt-warnings \ No newline at end of file diff --git a/test/files/run/t7582/InlineHolder.scala b/test/files/run/t7582/InlineHolder.scala index 3cbf233ce1..a18b9effaa 100644 --- a/test/files/run/t7582/InlineHolder.scala +++ b/test/files/run/t7582/InlineHolder.scala @@ -1,6 +1,3 @@ -/* - * filter: inliner warning; re-run with - */ package p1 { object InlineHolder { @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 diff --git a/test/files/run/t7582b.check b/test/files/run/t7582b.check index 0cfbf08886..58d0f19f5d 100644 --- a/test/files/run/t7582b.check +++ b/test/files/run/t7582b.check @@ -1 +1,6 @@ +InlineHolder.scala:9: warning: p1/InlineHolder$::inlinable()I is annotated @inline but could not be inlined: +The callee p1/InlineHolder$::inlinable()I contains the instruction INVOKESTATIC p1/PackageProtectedJava.protectedMethod ()I +that would cause an IllegalAccessError when inlined into class O$. + def x = p1.InlineHolder.inlinable + ^ 2 diff --git a/test/files/run/t7582b.flags b/test/files/run/t7582b.flags index 422d6be431..1f45833eff 100644 --- a/test/files/run/t7582b.flags +++ b/test/files/run/t7582b.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-Yopt:l:classpath -Yopt-warnings \ No newline at end of file diff --git a/test/files/run/t7582b/InlineHolder.scala b/test/files/run/t7582b/InlineHolder.scala index 3cbf233ce1..a18b9effaa 100644 --- a/test/files/run/t7582b/InlineHolder.scala +++ b/test/files/run/t7582b/InlineHolder.scala @@ -1,6 +1,3 @@ -/* - * filter: inliner warning; re-run with - */ package p1 { object InlineHolder { @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 diff --git a/test/files/run/t7807.check b/test/files/run/t7807.check new file mode 100644 index 0000000000..fd22077f2e --- /dev/null +++ b/test/files/run/t7807.check @@ -0,0 +1,3 @@ +... +... +... diff --git a/test/files/run/t7807.scala b/test/files/run/t7807.scala new file mode 100644 index 0000000000..8e3099ec14 --- /dev/null +++ b/test/files/run/t7807.scala @@ -0,0 +1,21 @@ +object Test { + def main(args: Array[String]) { + try { + println("...") + } + finally { + try { + println("...") + } + finally { + try { + println("...") + } + catch { + case ct: scala.util.control.ControlThrowable => throw(ct) + case t: Throwable => t.printStackTrace() + } + } + } + } +} diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/issues/OptimizedBytecodeTest.scala new file mode 100644 index 0000000000..3c6f1ff25e --- /dev/null +++ b/test/junit/scala/issues/OptimizedBytecodeTest.scala @@ -0,0 +1,331 @@ +package scala.issues + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test +import scala.tools.asm.Opcodes._ +import org.junit.Assert._ + +import scala.tools.nsc.backend.jvm.{AsmUtils, CodeGenTools} + +import CodeGenTools._ +import scala.tools.partest.ASMConverters +import ASMConverters._ +import AsmUtils._ + +import scala.tools.testing.ClearAfterClass + +object OptimizedBytecodeTest extends ClearAfterClass.Clearable { + val args = "-Yopt:l:classpath -Yopt-warnings" + var compiler = newCompiler(extraArgs = args) + def clear(): Unit = { compiler = null } +} + +@RunWith(classOf[JUnit4]) +class OptimizedBytecodeTest extends ClearAfterClass { + ClearAfterClass.stateToClear = OptimizedBytecodeTest + + val compiler = OptimizedBytecodeTest.compiler + + @Test + def t2171(): Unit = { + val code = + """class C { + | final def m(msg: => String) = try 0 catch { case ex: Throwable => println(msg) } + | def t(): Unit = while (true) m("...") + |} + """.stripMargin + val List(c) = compileClasses(compiler)(code) + assertSameCode(getSingleMethod(c, "t").instructions.dropNonOp, List(Label(0), Jump(GOTO, Label(0)))) + } + + @Test + def t3430(): Unit = { + val code = + """class C { + | final def m(f: String => Boolean) = f("a") + | def t(): Boolean = + | m { s1 => + | m { s2 => + | while (true) { } + | true + | } + | } + |} + """.stripMargin + val List(c) = compileClasses(compiler)(code) + + assertEquals( + getSingleMethod(c, "t").instructions.summary, + List(LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "C$$$anonfun$1", IRETURN)) + + assertEquals( + getSingleMethod(c, "C$$$anonfun$1").instructions.summary, + List(LDC, "C$$$anonfun$2", IRETURN)) + + assertEquals( + getSingleMethod(c, "C$$$anonfun$2").instructions.summary, + List(-1 /*A*/, GOTO /*A*/)) + } + + @Test + def t3252(): Unit = { + val code = + """class C { + | def t(x: Boolean): Thread = { + | g { + | x match { + | case false => Tat.h { } + | } + | } + | } + | + | private def g[T](block: => T) = ??? + |} + |object Tat { + | def h(block: => Unit): Nothing = ??? + |} + """.stripMargin + val List(c, t, tMod) = compileClasses(compiler)(code, allowMessage = _.msg.contains("not be exhaustive")) + assertEquals( + getSingleMethod(c, "t").instructions.summary, + List(GETSTATIC, "$qmark$qmark$qmark", ATHROW)) + } + + @Test + def t6157(): Unit = { + val code = + """class C { + | def t = println(ErrorHandler.defaultIfIOException("String")("String")) + |} + |object ErrorHandler { + | import java.io.IOException + | @inline + | def defaultIfIOException[T](default: => T)(closure: => T): T = try closure catch { + | case e: IOException => default + | } + |} + """.stripMargin + + val msg = + """ErrorHandler$::defaultIfIOException(Lscala/Function0;Lscala/Function0;)Ljava/lang/Object; is annotated @inline but could not be inlined: + |The operand stack at the callsite in C::t()V contains more values than the + |arguments expected by the callee ErrorHandler$::defaultIfIOException(Lscala/Function0;Lscala/Function0;)Ljava/lang/Object;. These values would be discarded + |when entering an exception handler declared in the inlined method.""".stripMargin + + compileClasses(compiler)(code, allowMessage = _.msg == msg) + } + + @Test + def t6547(): Unit = { // "pos" test -- check that it compiles + val code = + """trait ConfigurableDefault[@specialized V] { + | def fillArray(arr: Array[V], v: V) = (arr: Any) match { + | case x: Array[Int] => null + | case x: Array[Long] => v.asInstanceOf[Long] + | } + |} + """.stripMargin + compileClasses(compiler)(code) + } + + @Test + def t8062(): Unit = { + val c1 = + """package warmup + |object Warmup { def filter[A](p: Any => Boolean): Any = filter[Any](p) } + """.stripMargin + val c2 = "class C { def t = warmup.Warmup.filter[Any](x => false) }" + val List(c, _, _) = compileClassesSeparately(List(c1, c2), extraArgs = OptimizedBytecodeTest.args) + assertInvoke(getSingleMethod(c, "t"), "warmup/Warmup$", "filter") + } + + @Test + def t8306(): Unit = { // "pos" test + val code = + """class C { + | def foo: Int = 123 + | lazy val extension: Int = foo match { + | case idx if idx != -1 => 15 + | case _ => 17 + | } + |} + """.stripMargin + compileClasses(compiler)(code) + } + + @Test + def t8359(): Unit = { // "pos" test + // This is a minimization of code that crashed the compiler during bootstrapping + // in the first iteration of https://github.com/scala/scala/pull/4373, the PR + // that adjusted the order of free and declared params in LambdaLift. + + // Was: + // java.lang.AssertionError: assertion failed: + // Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1 + // at scala.tools.nsc.Global.assert(Global.scala:262) + // at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113) + // at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122) + // at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124) + val code = + """package test + |class Typer { + | def bar(a: Boolean, b: Boolean): Unit = { + | @inline + | def baz(): Unit = { + | ((_: Any) => (Typer.this, a, b)).apply("") + | } + | ((_: Any) => baz()).apply("") + | } + |} + """.stripMargin + compileClasses(compiler)(code) + } + + @Test + def t9123(): Unit = { // "pos" test + val code = + """trait Setting { + | type T + | def value: T + |} + |object Test { + | def test(x: Some[Setting]) = x match { + | case Some(dep) => Some(dep.value) map (_ => true) + | } + |} + """.stripMargin + compileClasses(compiler)(code) + } + + @Test + def traitForceInfo(): Unit = { + // This did NOT crash unless it's in the interactive package. + // error: java.lang.AssertionError: assertion failed: trait Contexts.NoContext$ linkedModule: List() + // at scala.Predef$.assert(Predef.scala:160) + // at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.innerSymbol$1(ClassfileParser.scala:1211) + // at scala.tools.nsc.symtab.classfile.ClassfileParser$innerClasses$.classSymbol(ClassfileParser.scala:1223) + // at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:489) + // at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:757) + // at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$1(ClassfileParser.scala:789) + val code = + """package scala.tools.nsc + |package interactive + | + |trait MyContextTrees { + | val self: Global + | val NoContext = self.analyzer.NoContext + |} + """.stripMargin + compileClasses(compiler)(code) + } + + @Test + def t9160(): Unit = { + val code = + """class C { + | def getInt: Int = 0 + | def t(trees: Object): Int = { + | trees match { + | case Some(elems) => + | case tree => getInt + | } + | 55 + | } + |} + """.stripMargin + val List(c) = compileClasses(compiler)(code) + assertEquals( + getSingleMethod(c, "t").instructions.summary, + List( + ALOAD /*1*/, INSTANCEOF /*Some*/, IFNE /*A*/, + ALOAD /*0*/, "getInt", POP, + -1 /*A*/, BIPUSH, IRETURN)) + } + + @Test + def t8796(): Unit = { + val code = + """final class C { + | def pr(): Unit = () + | def t(index: Int): Unit = index match { + | case 0 => pr() + | case 1 => pr() + | case _ => t(index - 2) + | } + |} + """.stripMargin + val List(c) = compileClasses(compiler)(code) + assertEquals( + getSingleMethod(c, "t").instructions.summary, + List( + -1 /*A*/, ILOAD /*1*/, TABLESWITCH, + -1, ALOAD, "pr", RETURN, + -1, ALOAD, "pr", RETURN, + -1, ILOAD, ICONST_2, ISUB, ISTORE, GOTO /*A*/)) + } + + @Test + def t8524(): Unit = { + val c1 = + """package library + |object Library { + | @inline def pleaseInlineMe() = 1 + | object Nested { @inline def pleaseInlineMe() = 2 } + |} + """.stripMargin + + val c2 = + """class C { + | def t = library.Library.pleaseInlineMe() + library.Library.Nested.pleaseInlineMe() + |} + """.stripMargin + + val cls = compileClassesSeparately(List(c1, c2), extraArgs = OptimizedBytecodeTest.args) + val c = cls.find(_.name == "C").get + assertEquals( + getSingleMethod(c, "t").instructions.summary, + List( + GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, // module load and null checks not yet eliminated + -1, ICONST_1, GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, + -1, ICONST_2, IADD, IRETURN)) + } + + @Test + def privateInline(): Unit = { + val code = + """final class C { + | private var x1 = false + | var x2 = false + | + | @inline private def wrapper1[T](body: => T): T = { + | val saved = x1 + | x1 = true + | try body + | finally x1 = saved + | } + | + | @inline private def wrapper2[T](body: => T): T = { + | val saved = x2 + | x2 = true + | try body + | finally x2 = saved + | } + | // inlined + | def f1a() = wrapper1(5) + | // not inlined: even after inlining `identity`, the Predef module is already on the stack for the + | // subsequent null check (the receiver of an inlined method, in this case Predef, is checked for + | // nullness, to ensure an NPE is thrown) + | def f1b() = identity(wrapper1(5)) + | + | def f2a() = wrapper2(5) // inlined + | def f2b() = identity(wrapper2(5)) // not inlined + |} + """.stripMargin + val List(c) = compileClasses(compiler)(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) + assertInvoke(getSingleMethod(c, "f1a"), "C", "C$$$anonfun$1") + assertInvoke(getSingleMethod(c, "f1b"), "C", "wrapper1") + assertInvoke(getSingleMethod(c, "f2a"), "C", "C$$$anonfun$3") + assertInvoke(getSingleMethod(c, "f2b"), "C", "wrapper2") + } +} diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index cef27b4d87..4d345ab9f7 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -134,4 +134,29 @@ class PatmatBytecodeTest extends ClearAfterClass { NEW, DUP, ALOAD /*1*/, "", ATHROW, /*R*/ -1, ALOAD /*2*/, ARETURN)) } + + @Test + def t6941(): Unit = { + val code = + """class C { + | def a(xs: List[Int]) = xs match { + | case x :: _ => x + | } + | def b(xs: List[Int]) = xs match { + | case xs: ::[Int] => xs.head + | } + |} + """.stripMargin + val c = compileClasses(optCompiler)(code, allowMessage = _.msg.contains("may not be exhaustive")).head + + val expected = List( + ALOAD /*1*/ , INSTANCEOF /*::*/ , IFEQ /*A*/ , + ALOAD, CHECKCAST /*::*/ , "head", "unboxToInt", + ISTORE, GOTO /*B*/ , + -1 /*A*/ , NEW /*MatchError*/ , DUP, ALOAD /*1*/ , "", ATHROW, + -1 /*B*/ , ILOAD, IRETURN) + + assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary, expected) + assertEquals(textify(findAsmMethod(c, "b")), getSingleMethod(c, "b").instructions.summary, expected) + } } diff --git a/test/pending/run/private-inline.check b/test/pending/run/private-inline.check deleted file mode 100644 index e71aec2fcf..0000000000 --- a/test/pending/run/private-inline.check +++ /dev/null @@ -1,13 +0,0 @@ -private-inline.scala:24: warning: Could not inline required method wrapper1 because callee contains exception handlers / finally clause, and is invoked with non-empty operand stack. - def f1b() = identity(wrapper1(5)) - ^ -private-inline.scala:24: warning: At the end of the day, could not inline @inline-marked method wrapper1 - def f1b() = identity(wrapper1(5)) - ^ -private-inline.scala:29: warning: Could not inline required method wrapper2 because callee contains exception handlers / finally clause, and is invoked with non-empty operand stack. - def f2b() = identity(wrapper2(5)) - ^ -private-inline.scala:29: warning: At the end of the day, could not inline @inline-marked method wrapper2 - def f2b() = identity(wrapper2(5)) - ^ -20 diff --git a/test/pending/run/private-inline.flags b/test/pending/run/private-inline.flags deleted file mode 100644 index c550fdce16..0000000000 --- a/test/pending/run/private-inline.flags +++ /dev/null @@ -1 +0,0 @@ --optimise -Yinline-warnings -Ybackend:GenASM diff --git a/test/pending/run/private-inline.scala b/test/pending/run/private-inline.scala deleted file mode 100644 index 60fef9efca..0000000000 --- a/test/pending/run/private-inline.scala +++ /dev/null @@ -1,52 +0,0 @@ - -final class A { - private var x1 = false - var x2 = false - - // manipulates private var - @inline private def wrapper1[T](body: => T): T = { - val saved = x1 - x1 = true - try body - finally x1 = saved - } - // manipulates public var - @inline private def wrapper2[T](body: => T): T = { - val saved = x2 - x2 = true - try body - finally x2 = saved - } - - // not inlined - def f1a() = wrapper1(5) - // inlined! - def f1b() = identity(wrapper1(5)) - - // not inlined - def f2a() = wrapper2(5) - // inlined! - def f2b() = identity(wrapper2(5)) -} - -object Test { - def methodClasses = List("f1a", "f2a") map ("A$$anonfun$" + _ + "$1") - - def main(args: Array[String]): Unit = { - val a = new A - import a._ - println(f1a() + f1b() + f2a() + f2b()) - - // Don't know how else to test this: all these should have been - // inlined, so all should fail. - methodClasses foreach { clazz => - - val foundClass = ( - try Class.forName(clazz) - catch { case _: Throwable => null } - ) - - assert(foundClass == null, foundClass) - } - } -} -- cgit v1.2.3