Skip to content

Commit

Permalink
Fix variance computation for parameterized type aliases
Browse files Browse the repository at this point in the history
The variance of a type alias was taken to be the variance of its
right-hand side, but that doesn't make sense for a parameterized type
alias which is free to appear in any position: variance checking should
only kick in when it is applied to something.

It was possible to work around this by using a type lambda instead of a
type alias, cats just had to do that: typelevel/cats#3264
  • Loading branch information
smarter committed Jan 21, 2020
1 parent f0e9c40 commit b7d9d19
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/reflect/scala/reflect/internal/Symbols.scala
Expand Up @@ -3076,7 +3076,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
extends TypeSymbol(initOwner, initPos, initName) {
type TypeOfClonedSymbol = TypeSymbol
override def variance = if (isLocalToThis) Bivariant else info.typeSymbol.variance
override def variance =
// A non-applied parameterized type alias can appear in any variance position
if (typeParams.nonEmpty)
Invariant
else if (isLocalToThis)
Bivariant
else
info.typeSymbol.variance

override def isContravariant = variance.isContravariant
override def isCovariant = variance.isCovariant
final override def isAliasType = true
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/variance-alias.check
@@ -0,0 +1,7 @@
variance-alias.scala:5: error: covariant type T occurs in invariant position in type => Inv[T] of value a
val a: Inv[({type L[+X] = X})#L[T]] = new Inv[({type L[+X] = X})#L[T]] {} // error
^
variance-alias.scala:6: error: covariant type T occurs in invariant position in type => Inv[X.this.Id[T]] of value b
val b: Inv[Id[T]] = new Inv[Id[T]] {} // error
^
2 errors
7 changes: 7 additions & 0 deletions test/files/neg/variance-alias.scala
@@ -0,0 +1,7 @@
trait Inv[A]

class X[+T] {
type Id[+A] = A
val a: Inv[({type L[+X] = X})#L[T]] = new Inv[({type L[+X] = X})#L[T]] {} // error
val b: Inv[Id[T]] = new Inv[Id[T]] {} // error
}
6 changes: 6 additions & 0 deletions test/files/pos/variance-alias.scala
@@ -0,0 +1,6 @@
trait Tc[F[_]]
object X {
type Id[+A] = A
val a: Tc[({type L[+X] = X})#L] = new Tc[({type L[+X] = X})#L] {} // ok, therefore the following should be too:
val b: Tc[Id] = new Tc[Id] {} // ok
}

0 comments on commit b7d9d19

Please sign in to comment.