summaryrefslogblamecommitdiff
path: root/test/files/run/manifests.scala
blob: 2d64bf18a9bce049f301ee8b67137bd83653e92f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11





                                        
 



                                                       
 

                                                                                                      


                                                                   




                                               
 




                                                                                           
 








                                                                                  
 




                                                                                                                             
 

                                                                                                                                 
 

                                                                        




                                  
   
 
                                       


                                               
                                       
 
                                       


                                                
                                       
 



                                                                                                                
 
                                                          
                               



                                  
 


                        

                        

                         
 








                                     
 






                                                    
 


                                                 
 







                                        
 







                                      
 







                                      
 










                                                     
object Test
{
  object Variances extends Enumeration {
    val CO, IN, CONTRA = Value
  }
  import Variances.{ CO, IN, CONTRA }

  object SubtypeRelationship extends Enumeration {
    val NONE, SAME, SUB, SUPER = Value
  }
  import SubtypeRelationship.{ NONE, SAME, SUB, SUPER }

  class VarianceTester[T, U, CC[_]](expected: Variances.Value)(
            implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) {

    def elements = List(ev1.tpe <:< ev2.tpe, ev2.tpe <:< ev1.tpe)
    def containers = List(ev3.tpe <:< ev4.tpe, ev4.tpe <:< ev3.tpe)

    def isUnrelated = typeCompare[T, U] == NONE
    def isSame = typeCompare[T, U] == SAME
    def isSub = typeCompare[T, U] == SUB
    def isSuper = typeCompare[T, U] == SUPER

    def showsCovariance = (elements == containers)
    def showsContravariance = (elements == containers.reverse)
    def showsInvariance = containers forall (_ == isSame)

    def allContainerVariances = List(showsCovariance, showsInvariance, showsContravariance)

    def showsExpectedVariance =
      if (isUnrelated) allContainerVariances forall (_ == false)
      else if (isSame) allContainerVariances forall (_ == true)
      else expected match {
        case CO     => showsCovariance && !showsContravariance && !showsInvariance
        case IN     => showsInvariance && !showsCovariance && !showsContravariance
        case CONTRA => showsContravariance && !showsCovariance && !showsInvariance
      }
  }

  def showsCovariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
    new VarianceTester[T, U, CC](CO) showsExpectedVariance

  def showsInvariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
    new VarianceTester[T, U, CC](IN) showsExpectedVariance

  def showsContravariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
    new VarianceTester[T, U, CC](CONTRA) showsExpectedVariance

  def typeCompare[T, U](implicit ev1: Manifest[T], ev2: Manifest[U]) = {
    (ev1.tpe <:< ev2.tpe, ev2.tpe <:< ev1.tpe) match {
      case (true, true)   => SAME
      case (true, false)  => SUB
      case (false, true)  => SUPER
      case (false, false) => NONE
    }
  }

  def assertAnyRef[T: Manifest] = List(
    manifest[T].tpe <:< manifest[Any].tpe,
    manifest[T].tpe <:< manifest[AnyRef].tpe,
    !(manifest[T].tpe <:< manifest[AnyVal].tpe)
  ) foreach (assert(_, "assertAnyRef"))

  def assertAnyVal[T: Manifest] = List(
    manifest[T].tpe <:< manifest[Any].tpe,
    !(manifest[T].tpe <:< manifest[AnyRef].tpe),
    manifest[T].tpe <:< manifest[AnyVal].tpe
  ) foreach (assert(_, "assertAnyVal"))

  def assertSameType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SAME, "assertSameType")
  def assertSuperType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SUPER, "assertSuperType")
  def assertSubType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SUB, "assertSubType")
  def assertNoRelationship[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == NONE, "assertNoRelationship")

  def testVariancesVia[T: Manifest, U: Manifest] = assert(
    typeCompare[T, U] == SUB &&
    showsCovariance[T, U, List] &&
    showsInvariance[T, U, Set],
    "testVariancesVia"
  )

  def runAllTests = {
    assertAnyVal[AnyVal]
    assertAnyVal[Unit]
    assertAnyVal[Int]
    assertAnyVal[Double]
    assertAnyVal[Boolean]
    assertAnyVal[Char]

    assertAnyRef[AnyRef]
    assertAnyRef[java.lang.Object]
    assertAnyRef[java.lang.Integer]
    assertAnyRef[java.lang.Double]
    assertAnyRef[java.lang.Boolean]
    assertAnyRef[java.lang.Character]
    assertAnyRef[String]
    assertAnyRef[scala.List[String]]
    assertAnyRef[scala.List[_]]

    // variance doesn't work yet
    // testVariancesVia[String, Any]
    // testVariancesVia[String, AnyRef]

    assertSubType[List[String], List[Any]]
    assertSubType[List[String], List[AnyRef]]
    assertNoRelationship[List[String], List[AnyVal]]

    assertSubType[List[Int], List[Any]]
    assertSubType[List[Int], List[AnyVal]]
    assertNoRelationship[List[Int], List[AnyRef]]

    // Nothing
    assertSubType[Nothing, Any]
    assertSubType[Nothing, AnyVal]
    assertSubType[Nothing, AnyRef]
    assertSubType[Nothing, String]
    assertSubType[Nothing, List[String]]
    assertSubType[Nothing, Null]
    assertSameType[Nothing, Nothing]

    // Null
    assertSubType[Null, Any]
    assertNoRelationship[Null, AnyVal]
    assertSubType[Null, AnyRef]
    assertSubType[Null, String]
    assertSubType[Null, List[String]]
    assertSameType[Null, Null]
    assertSuperType[Null, Nothing]

    // Any
    assertSameType[Any, Any]
    assertSuperType[Any, AnyVal]
    assertSuperType[Any, AnyRef]
    assertSuperType[Any, String]
    assertSuperType[Any, List[String]]
    assertSuperType[Any, Null]
    assertSuperType[Any, Nothing]

    // Misc unrelated types
    assertNoRelationship[Unit, AnyRef]
    assertNoRelationship[Unit, Int]
    assertNoRelationship[Int, Long]
    assertNoRelationship[Boolean, String]
    assertNoRelationship[List[Boolean], List[String]]
    assertNoRelationship[Set[Boolean], Set[String]]
  }

  def main(args: Array[String]): Unit = runAllTests
}