scala.reflect.internal.Variance.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spark-core Show documentation
Show all versions of spark-core Show documentation
Shaded version of Apache Spark 2.x.x for Presto
The newest version!
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* @author Paul Phillips
*/
package scala
package reflect
package internal
import Variance._
/** Variances form a lattice:
*
* - Covariant -
* / \
* Invariant Bivariant
* \ /
* Contravariant
*
* The variance of a symbol within a type is calculated based on variance
* annotations, e.g. +A or -A, and the positions of the types in which the
* symbol appears. The actual mechanics are beyond the scope of this
* comment, but the essential operations on a Variance are:
*
* '&' - like bitwise AND. Unless all inputs have compatible variance,
* folding them across & will be invariant.
* '*' - like multiplication across { -1, 0, 1 } with contravariance as -1.
* flip - if contravariant or covariant, flip to the other; otherwise leave unchanged.
* cut - if bivariant, remain bivariant; otherwise become invariant.
*
* There is an important distinction between "isPositive" and "isCovariant".
* The former is true for both Covariant and Bivariant, but the latter is true
* only for Covariant.
*/
final class Variance private (val flags: Int) extends AnyVal {
def isBivariant = flags == 2
def isCovariant = flags == 1 // excludes bivariant
def isInvariant = flags == 0
def isContravariant = flags == -1 // excludes bivariant
def isPositive = flags > 0 // covariant or bivariant
def &(other: Variance): Variance = (
if (this == other) this
else if (this.isBivariant) other
else if (other.isBivariant) this
else Invariant
)
def *(other: Variance): Variance = (
if (other.isPositive) this
else if (other.isContravariant) this.flip
else this.cut
)
/** Flip between covariant and contravariant. I chose not to use unary_- because it doesn't stand out enough. */
def flip = if (isCovariant) Contravariant else if (isContravariant) Covariant else this
/** Map everything below bivariant to invariant. */
def cut = if (isBivariant) this else Invariant
/** The symbolic annotation used to indicate the given kind of variance. */
def symbolicString = (
if (isCovariant) "+"
else if (isContravariant) "-"
else ""
)
override def toString = (
if (isContravariant) "contravariant"
else if (isCovariant) "covariant"
else if (isInvariant) "invariant"
else "" // noisy to print bivariant on everything without type parameters
)
}
object Variance {
implicit class SbtCompat(val v: Variance) {
def < (other: Int) = v.flags < other
def > (other: Int) = v.flags > other
}
def fold(variances: List[Variance]): Variance = (
if (variances.isEmpty) Bivariant
else variances reduceLeft (_ & _)
)
val Bivariant = new Variance(2)
val Covariant = new Variance(1)
val Contravariant = new Variance(-1)
val Invariant = new Variance(0)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy