With this piece of code:
trait B[T]
trait C[T]
class A[T] extends B[A[C[T]]]
I get the following error:
error: class graph is not finitary because type parameter T is expansively recursive
class A[T] extends B[A[C[T]]]
^
Can someone explain what the error message is about, why T is infinitely recursive and why the following code works?
class A[T] extends B[A[T]]
From the Scala 2.9 specification (note that this is in the Change Log as a change that was introduced in 2.4, so it’s not a “new restriction” in 2.9):
Kennedy and Pierce explain why infinitary class graphs are a problem:
Fortunately, as Kennedy and Pierce point out, there’s a convenient way to check whether a class graph is infinitary. I’m using their definitions throughout this answer.
First I’ll make your type variables distinct for clarity:
Next we construct the type parameter dependency graph using Kennedy and Pierce’s definition. The only declaration that’s going to add edges to the graph is the last one, for
A. They give the following rules for building the graph:So first we look at
ZandC[Z], which gives us a non-expansive edge fromZtoY. NextZandA[C[Z]]gives us an expansive edge fromZtoZ, andZandB[A[C[Z]]]gives us an expansive edge fromZtoX:I’ve indicated non-expansive edges with dashed arrows and expansive edges with solid ones. We have a cycle with an expansive edge, which is a problem:
This doesn’t happen for
class A[Z] extends B[A[Z]], which has the following graph:See the paper for a proof that a class table is infinitary iff it’s expansive.