The following code compiled fails, but it passed if I remove the specialized annotation in method dot.
Scala code runner version 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 try with no luck:
//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
This is a bug (also reproduces on 2.11.x). I've contacted the guys at LightBend, and this is definitely a quirk with the code generation for specialization and path dependent types. I've narrowed it down to a slim reproduce:
trait M[@specialized T] {
  type Res
  def res: Res
}
object Test {
  def m[@specialized T](op: M[T]): op.Res = op.res
}
The symbols for op will be out of sync and won't compile as you see in your code. @AdriaanMoors has opened a bug regarding this issue.
Adriaan has also pointed me to this blog post by Aleksandar Prokopec which points out some quirks in the @specilization code generation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With