summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala27
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala16
-rw-r--r--test/files/neg/elide-to-nothing.check4
-rw-r--r--test/files/neg/elide-to-nothing.flags1
-rw-r--r--test/files/neg/elide-to-nothing.scala31
-rw-r--r--test/files/run/elidable.check15
-rw-r--r--test/files/run/elidable.scala73
8 files changed, 33 insertions, 152 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index cc882ad5ed..e537c6b83f 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -250,19 +250,20 @@ abstract class TreeGen {
* var x: T = _
* which is appropriate to the given Type.
*/
- def mkZero(tp: Type): Tree = Literal(mkConstantZero(tp)) setType tp
-
- def mkConstantZero(tp: Type): Constant = tp.typeSymbol match {
- case UnitClass => Constant(())
- case BooleanClass => Constant(false)
- case FloatClass => Constant(0.0f)
- case DoubleClass => Constant(0.0d)
- case ByteClass => Constant(0.toByte)
- case ShortClass => Constant(0.toShort)
- case IntClass => Constant(0)
- case LongClass => Constant(0L)
- case CharClass => Constant(0.toChar)
- case _ => Constant(null)
+ def mkZero(tp: Type): Tree = {
+ val tree = tp.typeSymbol match {
+ case UnitClass => Literal(Constant())
+ case BooleanClass => Literal(Constant(false))
+ case FloatClass => Literal(Constant(0.0f))
+ case DoubleClass => Literal(Constant(0.0d))
+ case ByteClass => Literal(Constant(0.toByte))
+ case ShortClass => Literal(Constant(0.toShort))
+ case IntClass => Literal(Constant(0))
+ case LongClass => Literal(Constant(0L))
+ case CharClass => Literal(Constant(0.toChar))
+ case _ => Literal(Constant(null))
+ }
+ tree setType tp
}
def mkZeroContravariantAfterTyper(tp: Type): Tree = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index b9675b8270..9e801e3ea8 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -876,23 +876,7 @@ abstract class GenICode extends SubComponent {
val (newCtx, resKind) = genPrimitiveOp(app, ctx, expectedType)
generatedType = resKind
newCtx
- } else if (sym.elisionLevel.exists (_ < settings.elidebelow.value || settings.noassertions.value)) {
- // XXX settings.noassertions.value temporarily retained to avoid
- // breakage until a reasonable interface is settled upon.
- debuglog("Eliding call from " + tree.symbol.owner + " to " + sym +
- " based on its elision threshold of " + sym.elisionLevel.get)
- if (expectedType.isValueType) {
- ctx.bb.emit(CONSTANT(global.gen.mkConstantZero(expectedType.toType)), tree.pos)
- generatedType = expectedType
- }
- else if (expectedType.isNothingType) unit.error(tree.pos, "Cannot elide where Nothing is required.")
- else {
- ctx.bb.emit(CONSTANT(Constant(null)), tree.pos)
- generatedType = NullReference
- }
- ctx
- }
- else { // normal method call
+ } else { // normal method call
debuglog("Gen CALL_METHOD with sym: " + sym + " isStaticSymbol: " + sym.isStaticMember);
val invokeStyle =
if (sym.isStaticMember)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 8b735455ba..b458d305a5 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -452,6 +452,19 @@ abstract class UnCurry extends InfoTransform
}
}
+ /** For removing calls to specially designated methods.
+ */
+ def elideIntoUnit(tree: Tree): Tree = Literal(Constant()) setPos tree.pos setType UnitClass.tpe
+ def isElidable(tree: Tree) = {
+ val sym = treeInfo.methPart(tree).symbol
+ // XXX settings.noassertions.value temporarily retained to avoid
+ // breakage until a reasonable interface is settled upon.
+ sym != null && sym.elisionLevel.exists(x => x < settings.elidebelow.value || settings.noassertions.value) && {
+ log("Eliding call from " + tree.symbol.owner + " to " + sym + " based on its elision threshold of " + sym.elisionLevel.get)
+ true
+ }
+ }
+
// ------ The tree transformers --------------------------------------------------------
def mainTransform(tree: Tree): Tree = {
@@ -489,7 +502,8 @@ abstract class UnCurry extends InfoTransform
finally this.inConstructorFlag = saved
}
- tree match {
+ if (isElidable(tree)) elideIntoUnit(tree)
+ else tree match {
case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
if (dd.symbol hasAnnotation VarargsClass) saveRepeatedParams(dd)
withNeedLift(false) {
diff --git a/test/files/neg/elide-to-nothing.check b/test/files/neg/elide-to-nothing.check
deleted file mode 100644
index 3ef05aac9a..0000000000
--- a/test/files/neg/elide-to-nothing.check
+++ /dev/null
@@ -1,4 +0,0 @@
-elide-to-nothing.scala:14: error: Cannot elide where Nothing is required.
- val b: Nothing = unimplemented()
- ^
-one error found
diff --git a/test/files/neg/elide-to-nothing.flags b/test/files/neg/elide-to-nothing.flags
deleted file mode 100644
index 59a512e547..0000000000
--- a/test/files/neg/elide-to-nothing.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xelide-below 500
diff --git a/test/files/neg/elide-to-nothing.scala b/test/files/neg/elide-to-nothing.scala
deleted file mode 100644
index 5008e8bc1d..0000000000
--- a/test/files/neg/elide-to-nothing.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/** Test which should fail compilation */
-class ElysianFailed {
-
- import ElysianField._
-
- // fine
- val a: Int = myInt
-
- // fine
- unimplemented()
-
- // not fine
- val b: Nothing = unimplemented()
-
-}
-
-object ElysianField {
-
- import annotation.elidable
-
- @elidable(100) def unimplemented(): Nothing = throw new UnsupportedOperationException
-
- @elidable(100) def myInt: Int = 17
-
-}
-
-
-
-
-
diff --git a/test/files/run/elidable.check b/test/files/run/elidable.check
index 88cf98e0d1..4ce04f0040 100644
--- a/test/files/run/elidable.check
+++ b/test/files/run/elidable.check
@@ -1,14 +1 @@
-Good for me, I was not elided. Test.f3
-Good for me, I was not elided. O.f3
-Good for me, I was not elided. C.f1
-Good for me, I was not elided. C.f2
-()
-false
-0
-0
-0
-0
-0
-0.0
-0.0
-null
+Good for me, I was not elided.
diff --git a/test/files/run/elidable.scala b/test/files/run/elidable.scala
index a2f29d2caf..264efbad59 100644
--- a/test/files/run/elidable.scala
+++ b/test/files/run/elidable.scala
@@ -1,85 +1,16 @@
import annotation._
import elidable._
-trait T {
- @elidable(FINEST) def f1()
- @elidable(SEVERE) def f2()
- @elidable(FINEST) def f3() = assert(false, "Should have been elided.")
- def f4()
-}
-
-class C extends T {
- def f1() = println("Good for me, I was not elided. C.f1")
- def f2() = println("Good for me, I was not elided. C.f2")
- @elidable(FINEST) def f4() = assert(false, "Should have been elided.")
-}
-
-object O {
- @elidable(FINEST) def f1() = assert(false, "Should have been elided.")
- @elidable(INFO) def f2() = assert(false, "Should have been elided.")
- @elidable(SEVERE) def f3() = println("Good for me, I was not elided. O.f3")
- @elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).")
-}
-
object Test {
@elidable(FINEST) def f1() = assert(false, "Should have been elided.")
@elidable(INFO) def f2() = assert(false, "Should have been elided.")
- @elidable(SEVERE) def f3() = println("Good for me, I was not elided. Test.f3")
+ @elidable(SEVERE) def f3() = println("Good for me, I was not elided.")
@elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).")
-
- @elidable(FINEST) def f5() = {}
- @elidable(FINEST) def f6() = true
- @elidable(FINEST) def f7() = 1:Byte
- @elidable(FINEST) def f8() = 1:Short
- @elidable(FINEST) def f9() = 1:Char
- @elidable(FINEST) def fa() = 1
- @elidable(FINEST) def fb() = 1l
- @elidable(FINEST) def fc() = 1.0f
- @elidable(FINEST) def fd() = 1.0
- @elidable(FINEST) def fe() = "s"
-
+
def main(args: Array[String]): Unit = {
f1()
f2()
f3()
f4
- O.f1()
- O.f2()
- O.f3()
- O.f4
-
- val c = new C
- c.f1()
- c.f2()
- c.f3()
- c.f4()
-
- // make sure a return value is still available when eliding a call
- println(f5())
- println(f6())
- println(f7())
- println(f8())
- println(f9().toInt)
- println(fa())
- println(fb())
- println(fc())
- println(fd())
- println(fe())
-
- // this one won't show up in the output because a call to f1 is elidable when accessed through T
- (c:T).f1()
-
- // Test whether the method definitions are still available.
- List("Test", "Test$", "O", "O$", "C", "T") foreach { className =>
- List("f1", "f2", "f3", "f4") foreach { methodName =>
- Class.forName(className).getMethod(methodName)
- }
- }
- List("Test", "Test$") foreach { className =>
- List("f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe") foreach { methodName =>
- Class.forName(className).getMethod(methodName)
- }
- }
- Class.forName("T$class").getMethod("f3", classOf[T])
}
}