virtualeyes
virtualeyes

Reputation: 11237

Scala 2.11 Type Variance Changes

In Scala 2.10.4 this compiles:

trait Foo[-U,T]{
  type Contra = U
}

but in 2.11.0 the same fails with:

contravariant type U occurs in invariant position in type U of type Contra trait Foo[-U,T] {type Contra = U}

Is there a workaround available? Trying to port over a Scala library to 2.11 and the contravariant type is required in order to get a boatload of implicit defs picked up by the compiler (i.e. making U invariant doesn't seem to be an option).

Thanks

Upvotes: 5

Views: 318

Answers (2)

virtualeyes
virtualeyes

Reputation: 11237

Apparently post-2.7 and pre-2.11 this was a bug in the type checker. Now the prevention of approach in OP is a feature, which is a good thing, kind of o_O

The workaround is to do as one did pre-2.11, the difference being that now you know you're on your own, vs. before where you thought the compiler had your back.

Ignorance is bliss, right?

The workaround:

import annotation.unchecked._
trait Foo[-U,T]{
  type Contra = (U @uncheckedVariance)
}

Upvotes: 4

wheaties
wheaties

Reputation: 35980

I can't imagine there being a work around available. The reason I say this is all about supporting path-dependent types:

 def foo[T <: Foo[A,B]](that: T): that.Contra

which places the Contra type in the wrong position. You can not return a contravariant type as a result of an operation. Perhaps the search and validation of these requires so much work that the compiler authors decided this small corner case created too much of a burden or it is a compiler bug that you've uncovered.

By the way, this is just wild speculation on my part. I'd have to read the compiler code to figure out which way is which.

Upvotes: 4

Related Questions