diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala | 12 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 3 | ||||
-rw-r--r-- | test/files/pos/list-optim-check.flags | 1 | ||||
-rw-r--r-- | test/files/pos/list-optim-check.scala | 21 | ||||
-rw-r--r-- | test/files/run/t8334.scala | 17 |
5 files changed, 29 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index bf19bece8b..f9ba109358 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -239,6 +239,17 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // (1) A non-final method can be safe to inline if the receiver type is a final subclass. Example: // class A { @inline def f = 1 }; object B extends A; B.f // can be inlined // + // TODO: (1) doesn't cover the following example: + // trait TravLike { def map = ... } + // sealed trait List extends TravLike { ... } // assume map is not overridden + // final case class :: / final case object Nil + // (l: List).map // can be inlined + // we need to know that + // - the recevier is sealed + // - what are the children of the receiver + // - all children are final + // - none of the children overrides map + // // TODO: type analysis can render more calls statically resolved. Example: // new A.f // can be inlined, the receiver type is known to be exactly A. val isStaticallyResolved: Boolean = { @@ -336,6 +347,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { higherOrderParams: IntMap[ClassBType], calleeInfoWarning: Option[CalleeInfoWarning]) { assert(!(safeToInline && safeToRewrite), s"A callee of ${callee.name} can be either safeToInline or safeToRewrite, but not both.") + override def toString = s"Callee($calleeDeclarationClass.${callee.name})" } final case class ClosureInstantiation(lambdaMetaFactoryCall: LambdaMetaFactoryCall, ownerMethod: MethodNode, ownerClass: ClassBType) { diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 7b1997252d..eb095dbbc2 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -266,7 +266,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] (b.toList, these) } - @noinline // TODO - fix optimizer bug that requires noinline (see SI-8334) final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = { if (bf eq List.ReusableCBF) { if (this eq Nil) Nil.asInstanceOf[That] else { @@ -285,7 +284,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] else super.map(f) } - @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { if (bf eq List.ReusableCBF) { if (this eq Nil) Nil.asInstanceOf[That] else { @@ -315,7 +313,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] else super.collect(pf) } - @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) final override def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { if (bf eq List.ReusableCBF) { if (this eq Nil) Nil.asInstanceOf[That] else { diff --git a/test/files/pos/list-optim-check.flags b/test/files/pos/list-optim-check.flags deleted file mode 100644 index 49d036a887..0000000000 --- a/test/files/pos/list-optim-check.flags +++ /dev/null @@ -1 +0,0 @@ --optimize diff --git a/test/files/pos/list-optim-check.scala b/test/files/pos/list-optim-check.scala deleted file mode 100644 index f6e6ddec77..0000000000 --- a/test/files/pos/list-optim-check.scala +++ /dev/null @@ -1,21 +0,0 @@ -// Tests a map known to crash in optimizer with faster List map in SI-8240. -// Equivalent tests for collect and flatmap do not crash, but are provided -// anyway. -// See ticket SI-8334 for optimizer bug. -// TODO - Remove this test once SI-8334 is fixed and has its own test. -class A { - def f: Boolean = { - val xs = Nil map (_ => return false) - true - } - - def g: Boolean = { - val xs = Nil collect { case _ => return false } - true - } - - def h: Boolean = { - val xs = Nil flatMap { _ => return false } - true - } -} diff --git a/test/files/run/t8334.scala b/test/files/run/t8334.scala new file mode 100644 index 0000000000..bc7e97bd04 --- /dev/null +++ b/test/files/run/t8334.scala @@ -0,0 +1,17 @@ +object Test extends App { + def f: Boolean = { + val xs = Nil map (_ => return false) + true + } + + def g: Boolean = { + val xs = Nil collect { case _ => return false } + true + } + + def h: Boolean = { + val xs = Nil flatMap { _ => return false } + true + } + assert(f && g && h) +} |