Is this a scala specialized bug?

The following compiled code fails, but it is passed if I delete the specialized annotation in the dot method.

Scala version for code 2.12.0-RC2 - Copyright 2002-2016, LAMP / EPFL and Lightbend, Inc.

 abstract class Op[@specialized Left, @specialized Right] { @specialized type Result def r: Numeric[Result] def times(left: Left, right: Right): Result } object Op { implicit object IntDoubleOp extends Op[Int, Double] { type Result = Double val r = implicitly[Numeric[Double]] def times(left: Int, right: Double): Double = left * right } } object calc { def dot[@specialized Left, @specialized Right](xs: Array[Left], ys: Array[Right]) (implicit op: Op[Left, Right]): op.Result = { var total = op.r.zero var index = xs.length while(index > 0) { index -= 1 total = op.r.plus(total, op.times(xs(index), ys(index))) } total } } 

 test.scala:31: error: type mismatch; found : op.Result required: op.Result total ^ one error found 

Here is another no-luck attempt:

 //cat Ops.scala import scala.{ specialized => sp } trait OpsResult { type N } trait SymOps extends OpsResult { @sp override type N def zero: N def plus(left: N, right: N): N } trait AsyOps[@sp L, @sp R] extends OpsResult { @sp override type N def times(left: L, right: R): N } trait MixOps[@sp L, @sp R] extends AsyOps[L, R] with SymOps object MixOps { trait DoubleOps extends SymOps { override type N = Double def zero: Double = 0.0 override def plus(left: Double, right: Double): Double = left + right } trait IntDoubleOps extends AsyOps[Int, Double] { override type N = Double override def times(left: Int, right: Double): Double = left * right } implicit object MixIntDouble extends IntDoubleOps with DoubleOps } object Test { def dot[@sp L, @sp R](xs: Array[L], ys: Array[R]) (implicit op: MixOps[L, R]): op.N = { op.zero } } 

 $ scalac Ops.scala Ops.scala:36: error: type mismatch; found : op.N required: op.N op.zero ^ one error found 
+5
source share
1 answer

This is an error (also reproduced on 2.11.x). I contacted the guys at LightBend, and this is definitely a quirk with code generation for specialization and type-dependent types. I narrowed it down to subtle playback:

 trait M[@specialized T] { type Res def res: Res } object Test { def m[@specialized T](op: M[T]): op.Res = op.res } 

The characters for op will not be synchronized and will not compile, as you see in your code. @AdriaanMoors discovered an error regarding this issue.

Adriaan also pointed me to this blog post from Aleksandar Prokopec, which points out some quirks in @specilization code @specilization .

+5
source

Source: https://habr.com/ru/post/1258701/


All Articles