@@ -40,6 +40,7 @@ object Types {
40
40
* | | +--- ConstantType
41
41
* | | +--- MethodParam
42
42
* | | +--- RefinedThis
43
+ * | | +--- NoPrefix
43
44
* | +- TypeBounds
44
45
* | +- ExprType
45
46
* | +- AnnotatedType
@@ -440,24 +441,72 @@ object Types {
440
441
case _ => Nil
441
442
}
442
443
443
- final def applyToArgs (args : List [Type ])(implicit ctx : Context ) = {
444
- def loop (tp : Type , tparams : List [TypeSymbol ], args : List [Type ]): Type = args match {
444
+ /** Encode the type resulting from applying this type to given arguments */
445
+ final def appliedTo (args : List [Type ])(implicit ctx : Context ): Type = {
446
+ def recur (tp : Type , tparams : List [TypeSymbol ], args : List [Type ]): Type = args match {
445
447
case arg :: args1 =>
446
448
val tparam = tparams.head
447
- val tp1 = RefinedType (tp, tparam.name, tp.toAlias (tparam))
448
- loop (tp1, tparams.tail, args1)
449
+ val tp1 = RefinedType (tp, tparam.name, arg.toRHS (tparam))
450
+ recur (tp1, tparams.tail, args1)
449
451
case nil => tp
450
452
}
451
- if (args.isEmpty) this else loop (this , typeParams, args)
453
+ if (args.isEmpty) this else recur (this , typeParams, args)
452
454
}
453
455
454
- final def toAlias (tparam : Symbol )(implicit ctx : Context ): TypeBounds = {
455
- val flags = tparam.flags
456
- if (flags is Covariant ) TypeBounds (defn.NothingType , this )
457
- else if (flags is Contravariant ) TypeBounds (this , defn.AnyType )
456
+ final def appliedTo (args : Type * )(implicit ctx : Context ): Type = appliedTo(args.toList)
457
+
458
+ /** If this type equals `tycon applyToArgs args`, for some
459
+ * non-refinement type `tycon` and (possibly partial) type arguments
460
+ * `args`, return a pair consisting of `tycon` and `args`.
461
+ * Otherwise return the type itself and `Nil`.
462
+ */
463
+ final def splitArgs (implicit ctx : Context ): (Type , List [Type ]) = {
464
+ def recur (tp : Type , nparams : Int ): (Type , List [Type ]) = tp match {
465
+ case tp @ RefinedType (parent, name) =>
466
+ def fail = (NoType , Nil )
467
+ if (nparams >= 0 ) {
468
+ val result @ (tycon, args) = recur(parent, nparams - 1 )
469
+ if (tycon != NoType ) {
470
+ val tparam = tycon.typeParams.apply(nparams)
471
+ if (tparam.name == name) {
472
+ (tycon, args :+ tp.info.argType(tparam))
473
+ } else fail
474
+ } else fail
475
+ } else fail
476
+ case tp =>
477
+ (tp, Nil )
478
+ }
479
+ val result @ (tycon, args) = recur(this , typeParams.length)
480
+ if (tycon != NoType ) result else (this , Nil )
481
+ }
482
+
483
+ final def splitArgsCompletely (implicit ctx : Context ): (Type , List [Type ]) = {
484
+ val result @ (tycon, args) = splitArgs
485
+ if (args.length == tycon.typeParams.length) result else (NoType , Nil )
486
+ }
487
+
488
+ /** Turn this type into a TypeBounds RHS */
489
+ final def toRHS (tparam : Symbol )(implicit ctx : Context ): TypeBounds = {
490
+ val v = tparam.variance
491
+ if (v > 0 ) TypeBounds (defn.NothingType , this )
492
+ else if (v < 0 ) TypeBounds (this , defn.AnyType )
458
493
else TypeBounds (this , this )
459
494
}
460
495
496
+ /** If this is the image of a type argument, recover the type argument,
497
+ * otherwise NoType.
498
+ */
499
+ final def argType (tparam : Symbol )(implicit ctx : Context ): Type = this match {
500
+ case TypeBounds (lo, hi) =>
501
+ val v = tparam.variance
502
+ if (v > 0 && lo.typeSymbol == defn.NothingClass ) hi
503
+ else if (v < 0 && hi.typeSymbol == defn.AnyClass ) lo
504
+ else if (v == 0 && (lo eq hi)) lo
505
+ else NoType
506
+ case _ =>
507
+ NoType
508
+ }
509
+
461
510
final def isWrong : Boolean = ! exists // !!! needed?
462
511
final def exists : Boolean = true
463
512
@@ -661,7 +710,7 @@ object Types {
661
710
}
662
711
}
663
712
664
- final class TermRefBySym (prefix : Type , val fixedSym : TermSymbol )(implicit initctx : Context )
713
+ final class TermRefBySym (prefix : Type , val fixedSym : TermSymbol )(initctx : Context )
665
714
extends TermRef (prefix, fixedSym.name(initctx).asTermName) with HasFixedSym {
666
715
}
667
716
@@ -671,7 +720,7 @@ object Types {
671
720
super .loadDenot.atSignature(signature)
672
721
}
673
722
674
- final class TypeRefBySym (prefix : Type , val fixedSym : TypeSymbol )(implicit initctx : Context )
723
+ final class TypeRefBySym (prefix : Type , val fixedSym : TypeSymbol )(initctx : Context )
675
724
extends TypeRef (prefix, fixedSym.name(initctx).asTypeName) with HasFixedSym {
676
725
}
677
726
@@ -1017,6 +1066,7 @@ object Types {
1017
1066
final class CachedTypeBounds (lo : Type , hi : Type ) extends TypeBounds (lo, hi)
1018
1067
1019
1068
object TypeBounds {
1069
+ def empty (implicit ctx : Context ) = apply(defn.NothingType , defn.AnyType )
1020
1070
def apply (lo : Type , hi : Type )(implicit ctx : Context ) =
1021
1071
unique(new CachedTypeBounds (lo, hi))
1022
1072
}
0 commit comments