@@ -111,6 +111,7 @@ object Types {
111111 /** Does this type denote a stable reference (i.e. singleton type)? */
112112 final def isStable (implicit ctx : Context ): Boolean = stripTypeVar match {
113113 case tp : TermRef => tp.termSymbol.isStable && tp.prefix.isStable || tp.info.isStable
114+ case tp : AppliedTermRef => tp.fn.isStable && tp.args.forall(_.isStable)
114115 case _ : SingletonType | NoPrefix => true
115116 case tp : RefinedOrRecType => tp.parent.isStable
116117 case tp : ExprType => tp.resultType.isStable
@@ -286,14 +287,14 @@ object Types {
286287 /** Is this the type of a method that has a repeated parameter type as
287288 * last parameter type?
288289 */
289- def isVarArgsMethod (implicit ctx : Context ): Boolean = stripPoly match {
290+ def isVarArgsMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
290291 case mt : MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam
291292 case _ => false
292293 }
293294
294295 /** Is this the type of a method with a leading empty parameter list?
295296 */
296- def isNullaryMethod (implicit ctx : Context ): Boolean = stripPoly match {
297+ def isNullaryMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
297298 case MethodType (Nil ) => true
298299 case _ => false
299300 }
@@ -896,9 +897,11 @@ object Types {
896897 */
897898 def stripAnnots (implicit ctx : Context ): Type = this
898899
899- /** Strip PolyType prefix */
900- def stripPoly (implicit ctx : Context ): Type = this match {
901- case tp : PolyType => tp.resType.stripPoly
900+ /** Strip PolyType and AppliedTermRef prefix */
901+ // NOTE(gsps): Usages of this method always match on MethodType, so we generalize it to stripping AppliedTermRef.
902+ def stripMethodPrefix (implicit ctx : Context ): Type = this match {
903+ case tp : PolyType => tp.resType.stripMethodPrefix
904+ case tp : AppliedTermRef => tp.resType.stripMethodPrefix
902905 case _ => this
903906 }
904907
@@ -1209,26 +1212,26 @@ object Types {
12091212 }
12101213
12111214 /** The parameter types of a PolyType or MethodType, Empty list for others */
1212- final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripPoly match {
1215+ final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripMethodPrefix match {
12131216 case mt : MethodType => mt.paramInfos :: mt.resultType.paramInfoss
12141217 case _ => Nil
12151218 }
12161219
12171220 /** The parameter names of a PolyType or MethodType, Empty list for others */
1218- final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripPoly match {
1221+ final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripMethodPrefix match {
12191222 case mt : MethodType => mt.paramNames :: mt.resultType.paramNamess
12201223 case _ => Nil
12211224 }
12221225
12231226
12241227 /** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
1225- final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripPoly match {
1228+ final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripMethodPrefix match {
12261229 case mt : MethodType => mt.paramInfos
12271230 case _ => Nil
12281231 }
12291232
12301233 /** Is this either not a method at all, or a parameterless method? */
1231- final def isParameterless (implicit ctx : Context ): Boolean = stripPoly match {
1234+ final def isParameterless (implicit ctx : Context ): Boolean = stripMethodPrefix match {
12321235 case mt : MethodType => false
12331236 case _ => true
12341237 }
@@ -1239,7 +1242,7 @@ object Types {
12391242 /** The final result type of a PolyType, MethodType, or ExprType, after skipping
12401243 * all parameter sections, the type itself for all others.
12411244 */
1242- def finalResultType (implicit ctx : Context ): Type = resultType.stripPoly match {
1245+ def finalResultType (implicit ctx : Context ): Type = resultType.stripMethodPrefix match {
12431246 case mt : MethodType => mt.resultType.finalResultType
12441247 case _ => resultType
12451248 }
@@ -2123,6 +2126,55 @@ object Types {
21232126 apply(prefix, if (denot.symbol.exists) denot.symbol.asType else name).withDenot(denot)
21242127 }
21252128
2129+ // --- AppliedTermRef ---------------------------------------------------------------------
2130+
2131+ /** An opaque representation of a term-level application. **/
2132+ abstract case class AppliedTermRef (fn : /* TermRef | AppliedTermRef*/ SingletonType , args : List [Type ])
2133+ extends CachedProxyType with SingletonType
2134+ {
2135+ protected [this ] var myResType : Type = _
2136+ def resType (implicit ctx : Context ): Type = {
2137+ if (myResType == null )
2138+ // FIXME(gsps): Sometimes TermRef(TermParamRef(<fun>, 1), +) might not have a denot, e.g., when calling
2139+ // def add[X<:Int, Y<:Int, Z<:Int](x: X, y: Y, z: {x + y}): z.type = z
2140+ fn.widen match {
2141+ case methTpe : MethodType => myResType = ctx.typer.applicationResultType(methTpe, args)
2142+ }
2143+ myResType
2144+ }
2145+
2146+ def underlying (implicit ctx : Context ): Type = resType
2147+
2148+ def derivedAppliedTerm (fn : Type , args : List [Type ])(implicit ctx : Context ): Type =
2149+ if ((this .fn eq fn) && (this .args eq args)) this
2150+ else AppliedTermRef (fn, args)
2151+
2152+ override def computeHash = doHash(fn, args)
2153+
2154+ override def eql (that : Type ) = that match {
2155+ case that : AppliedTermRef => (this .fn eq that.fn) && this .args.eqElements(that.args)
2156+ case _ => false
2157+ }
2158+ }
2159+
2160+ final class CachedAppliedTermRef (fn : SingletonType , args : List [Type ]) extends AppliedTermRef (fn, args)
2161+
2162+ object AppliedTermRef {
2163+ def apply (fn : Type , args : List [Type ])(implicit ctx : Context ): Type = {
2164+ assertUnerased()
2165+ fn.dealias match {
2166+ case fn : TermRef => unique(new CachedAppliedTermRef (fn, args))
2167+ case fn : AppliedTermRef => unique(new CachedAppliedTermRef (fn, args))
2168+ case _ =>
2169+ fn.widenDealias match {
2170+ case methTpe : MethodType => ctx.typer.applicationResultType(methTpe, args) // TODO(gsps): Check length?
2171+ case _ : WildcardType => WildcardType
2172+ case tp => throw new AssertionError (i " Don't know how to apply $tp. " )
2173+ }
2174+ }
2175+ }
2176+ }
2177+
21262178 // --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
21272179
21282180 /** The type cls.this
@@ -3677,7 +3729,7 @@ object Types {
36773729 object SAMType {
36783730 def zeroParamClass (tp : Type )(implicit ctx : Context ): Type = tp match {
36793731 case tp : ClassInfo =>
3680- def zeroParams (tp : Type ): Boolean = tp.stripPoly match {
3732+ def zeroParams (tp : Type ): Boolean = tp.stripMethodPrefix match {
36813733 case mt : MethodType => mt.paramInfos.isEmpty && ! mt.resultType.isInstanceOf [MethodType ]
36823734 case et : ExprType => true
36833735 case _ => false
@@ -3763,6 +3815,8 @@ object Types {
37633815 tp.derivedSuperType(thistp, supertp)
37643816 protected def derivedAppliedType (tp : AppliedType , tycon : Type , args : List [Type ]): Type =
37653817 tp.derivedAppliedType(tycon, args)
3818+ protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
3819+ tp.derivedAppliedTerm(fn, args)
37663820 protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ): Type =
37673821 tp.derivedAndOrType(tp1, tp2)
37683822 protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ): Type =
@@ -3816,6 +3870,9 @@ object Types {
38163870 }
38173871 derivedAppliedType(tp, this (tp.tycon), mapArgs(tp.args, tp.typeParams))
38183872
3873+ case tp : AppliedTermRef =>
3874+ derivedAppliedTerm(tp, this (tp.fn), tp.args.mapConserve(this ))
3875+
38193876 case tp : RefinedType =>
38203877 derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
38213878
@@ -4109,6 +4166,25 @@ object Types {
41094166 else tp.derivedAppliedType(tycon, args)
41104167 }
41114168
4169+ override protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
4170+ fn match {
4171+ case Range (fnLo, fnHi) =>
4172+ range(derivedAppliedTerm(tp, fnLo, args), derivedAppliedTerm(tp, fnHi, args))
4173+ case _ =>
4174+ if (fn.isBottomType) {
4175+ fn
4176+ } else if (args.exists(isRange)) {
4177+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
4178+ args foreach {
4179+ case Range (lo, hi) => loBuf += lo; hiBuf += hi
4180+ case arg => loBuf += arg; hiBuf += arg
4181+ }
4182+ range(tp.derivedAppliedTerm(fn, loBuf.toList), tp.derivedAppliedTerm(fn, hiBuf.toList))
4183+ } else {
4184+ tp.derivedAppliedTerm(fn, args)
4185+ }
4186+ }
4187+
41124188 override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
41134189 if (isRange(tp1) || isRange(tp2))
41144190 if (tp.isAnd) range(lower(tp1) & lower(tp2), upper(tp1) & upper(tp2))
@@ -4197,6 +4273,9 @@ object Types {
41974273 }
41984274 foldArgs(this (x, tycon), tp.typeParams, args)
41994275
4276+ case tp : AppliedTermRef =>
4277+ foldOver(this (x, tp.fn), tp.args)
4278+
42004279 case _ : BoundType | _ : ThisType => x
42014280
42024281 case tp : LambdaType =>
0 commit comments