Skip to content

Commit

Permalink
Merge pull request #9461 from retronym/spire-array-regression
Browse files Browse the repository at this point in the history
  • Loading branch information
SethTisue committed Jan 28, 2021
2 parents a9b6d67 + c969213 commit 5f6e5a1
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/transform/CleanUp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ abstract class CleanUp extends Statics with Transform with ast.TreeDSL {
// See scala/bug#6611; we must *only* do this for literal vararg arrays.
case Apply(appMeth, Apply(wrapRefArrayMeth, (arg @ StripCast(ArrayValue(elemtpt, elems))) :: Nil) :: classTagEvidence :: Nil)
if (wrapRefArrayMeth.symbol == currentRun.runDefinitions.Predef_genericWrapRefArray || wrapRefArrayMeth.symbol == currentRun.runDefinitions.Predef_wrapRefArray) && appMeth.symbol == ArrayModule_genericApply &&
!elemtpt.tpe.typeSymbol.isBottomClass =>
!elemtpt.tpe.typeSymbol.isBottomClass && !elemtpt.tpe.typeSymbol.isPrimitiveValueClass /* can happen via specialization.*/ =>
classTagEvidence.attachments.get[analyzer.MacroExpansionAttachment] match {
case Some(att) if att.expandee.symbol.name == nme.materializeClassTag && tree.isInstanceOf[ApplyToImplicitArgs] =>
super.transform(arg)
Expand Down
27 changes: 19 additions & 8 deletions src/library/scala/Array.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
package scala

import scala.collection.generic._
import scala.collection.{ mutable, immutable }
import mutable.{ ArrayBuilder, ArraySeq }
import scala.reflect.ClassTag
import scala.runtime.ScalaRunTime.{ array_apply, array_update }
import scala.collection.{immutable, mutable}
import mutable.{ArrayBuilder, ArraySeq}
import scala.reflect.{ClassTag, classTag}
import scala.runtime.ScalaRunTime
import scala.runtime.ScalaRunTime.{array_apply, array_update}

/** Contains a fallback builder for arrays when the element type
* does not have a class tag. In that case a generic array is built.
Expand Down Expand Up @@ -194,10 +195,20 @@ object Array extends FallbackArrayBuilding {
// Subject to a compiler optimization in Cleanup.
// Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a }
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
val len = xs.length
xs match {
case wa: mutable.WrappedArray[_] if wa.elemTag == classTag[T] =>
// We get here in test/files/run/sd760a.scala, `Array[T](t)` for
// a specialized type parameter `T`. While we still pay for two
// copies of the array it is better than before when we also boxed
// each element when populating the result.
ScalaRunTime.array_clone(wa.array).asInstanceOf[Array[T]]
case _ =>
val array = new Array[T](len)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
}

/** Creates an array of `Boolean` objects */
Expand Down
12 changes: 12 additions & 0 deletions test/files/run/array-cleanup-optimation-specialized.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import scala.reflect.ClassTag

object Test {
def main(args: Array[String]): Unit = {
assert(apply[String]("") == classOf[Array[String]])
assert(apply[Double](1d) == classOf[Array[Double]])
}

def apply[@specialized(Double) C: ClassTag](c: C): Class[_] = {
Array(c).getClass
}
}
12 changes: 12 additions & 0 deletions test/files/run/sd760a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import scala.reflect.ClassTag

object Test {
def main(args: Array[String]): Unit = {
assert(apply[String]("") == classOf[Array[String]])
assert(apply[Double](1d) == classOf[Array[Double]])
}

def apply[@specialized(Double) C: ClassTag](c: C): Class[_] = {
Array(c).getClass
}
}
11 changes: 11 additions & 0 deletions test/files/run/sd760b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import scala.reflect.ClassTag

object Test {
def main(args: Array[String]): Unit = {
assert(apply[Double](1d) == classOf[Array[Double]])
}

def apply[D <: Double: ClassTag](d: D): Class[_] = {
Array.apply[D](d).getClass
}
}

0 comments on commit 5f6e5a1

Please sign in to comment.