@@ -111,6 +111,7 @@ object Types {
111
111
/** Does this type denote a stable reference (i.e. singleton type)? */
112
112
final def isStable (implicit ctx : Context ): Boolean = stripTypeVar match {
113
113
case tp : TermRef => tp.termSymbol.isStable && tp.prefix.isStable || tp.info.isStable
114
+ case tp : AppliedTermRef => tp.fn.isStable && tp.args.forall(_.isStable)
114
115
case _ : SingletonType | NoPrefix => true
115
116
case tp : RefinedOrRecType => tp.parent.isStable
116
117
case tp : ExprType => tp.resultType.isStable
@@ -286,14 +287,14 @@ object Types {
286
287
/** Is this the type of a method that has a repeated parameter type as
287
288
* last parameter type?
288
289
*/
289
- def isVarArgsMethod (implicit ctx : Context ): Boolean = stripPoly match {
290
+ def isVarArgsMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
290
291
case mt : MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam
291
292
case _ => false
292
293
}
293
294
294
295
/** Is this the type of a method with a leading empty parameter list?
295
296
*/
296
- def isNullaryMethod (implicit ctx : Context ): Boolean = stripPoly match {
297
+ def isNullaryMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
297
298
case MethodType (Nil ) => true
298
299
case _ => false
299
300
}
@@ -896,9 +897,11 @@ object Types {
896
897
*/
897
898
def stripAnnots (implicit ctx : Context ): Type = this
898
899
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
902
905
case _ => this
903
906
}
904
907
@@ -1209,26 +1212,26 @@ object Types {
1209
1212
}
1210
1213
1211
1214
/** 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 {
1213
1216
case mt : MethodType => mt.paramInfos :: mt.resultType.paramInfoss
1214
1217
case _ => Nil
1215
1218
}
1216
1219
1217
1220
/** 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 {
1219
1222
case mt : MethodType => mt.paramNames :: mt.resultType.paramNamess
1220
1223
case _ => Nil
1221
1224
}
1222
1225
1223
1226
1224
1227
/** 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 {
1226
1229
case mt : MethodType => mt.paramInfos
1227
1230
case _ => Nil
1228
1231
}
1229
1232
1230
1233
/** 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 {
1232
1235
case mt : MethodType => false
1233
1236
case _ => true
1234
1237
}
@@ -1239,7 +1242,7 @@ object Types {
1239
1242
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
1240
1243
* all parameter sections, the type itself for all others.
1241
1244
*/
1242
- def finalResultType (implicit ctx : Context ): Type = resultType.stripPoly match {
1245
+ def finalResultType (implicit ctx : Context ): Type = resultType.stripMethodPrefix match {
1243
1246
case mt : MethodType => mt.resultType.finalResultType
1244
1247
case _ => resultType
1245
1248
}
@@ -2123,6 +2126,55 @@ object Types {
2123
2126
apply(prefix, if (denot.symbol.exists) denot.symbol.asType else name).withDenot(denot)
2124
2127
}
2125
2128
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
+
2126
2178
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
2127
2179
2128
2180
/** The type cls.this
@@ -3677,7 +3729,7 @@ object Types {
3677
3729
object SAMType {
3678
3730
def zeroParamClass (tp : Type )(implicit ctx : Context ): Type = tp match {
3679
3731
case tp : ClassInfo =>
3680
- def zeroParams (tp : Type ): Boolean = tp.stripPoly match {
3732
+ def zeroParams (tp : Type ): Boolean = tp.stripMethodPrefix match {
3681
3733
case mt : MethodType => mt.paramInfos.isEmpty && ! mt.resultType.isInstanceOf [MethodType ]
3682
3734
case et : ExprType => true
3683
3735
case _ => false
@@ -3763,6 +3815,8 @@ object Types {
3763
3815
tp.derivedSuperType(thistp, supertp)
3764
3816
protected def derivedAppliedType (tp : AppliedType , tycon : Type , args : List [Type ]): Type =
3765
3817
tp.derivedAppliedType(tycon, args)
3818
+ protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
3819
+ tp.derivedAppliedTerm(fn, args)
3766
3820
protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ): Type =
3767
3821
tp.derivedAndOrType(tp1, tp2)
3768
3822
protected def derivedAnnotatedType (tp : AnnotatedType , underlying : Type , annot : Annotation ): Type =
@@ -3816,6 +3870,9 @@ object Types {
3816
3870
}
3817
3871
derivedAppliedType(tp, this (tp.tycon), mapArgs(tp.args, tp.typeParams))
3818
3872
3873
+ case tp : AppliedTermRef =>
3874
+ derivedAppliedTerm(tp, this (tp.fn), tp.args.mapConserve(this ))
3875
+
3819
3876
case tp : RefinedType =>
3820
3877
derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
3821
3878
@@ -4109,6 +4166,25 @@ object Types {
4109
4166
else tp.derivedAppliedType(tycon, args)
4110
4167
}
4111
4168
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
+
4112
4188
override protected def derivedAndOrType (tp : AndOrType , tp1 : Type , tp2 : Type ) =
4113
4189
if (isRange(tp1) || isRange(tp2))
4114
4190
if (tp.isAnd) range(lower(tp1) & lower(tp2), upper(tp1) & upper(tp2))
@@ -4197,6 +4273,9 @@ object Types {
4197
4273
}
4198
4274
foldArgs(this (x, tycon), tp.typeParams, args)
4199
4275
4276
+ case tp : AppliedTermRef =>
4277
+ foldOver(this (x, tp.fn), tp.args)
4278
+
4200
4279
case _ : BoundType | _ : ThisType => x
4201
4280
4202
4281
case tp : LambdaType =>
0 commit comments