@@ -148,6 +148,7 @@ object Types {
148
148
/** Does this type denote a stable reference (i.e. singleton type)? */
149
149
final def isStable (implicit ctx : Context ): Boolean = stripTypeVar match {
150
150
case tp : TermRef => tp.termSymbol.isStable && tp.prefix.isStable || tp.info.isStable
151
+ case tp : AppliedTermRef => tp.fn.isStable && tp.args.forall(_.isStable)
151
152
case _ : SingletonType | NoPrefix => true
152
153
case tp : RefinedOrRecType => tp.parent.isStable
153
154
case tp : ExprType => tp.resultType.isStable
@@ -279,14 +280,14 @@ object Types {
279
280
/** Is this the type of a method that has a repeated parameter type as
280
281
* last parameter type?
281
282
*/
282
- def isVarArgsMethod (implicit ctx : Context ): Boolean = stripPoly match {
283
+ def isVarArgsMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
283
284
case mt : MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam
284
285
case _ => false
285
286
}
286
287
287
288
/** Is this the type of a method with a leading empty parameter list?
288
289
*/
289
- def isNullaryMethod (implicit ctx : Context ): Boolean = stripPoly match {
290
+ def isNullaryMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
290
291
case MethodType (Nil ) => true
291
292
case _ => false
292
293
}
@@ -903,9 +904,10 @@ object Types {
903
904
*/
904
905
def stripAnnots (implicit ctx : Context ): Type = this
905
906
906
- /** Strip PolyType prefix */
907
- def stripPoly (implicit ctx : Context ): Type = this match {
908
- case tp : PolyType => tp.resType.stripPoly
907
+ /** Strip PolyType and AppliedTermRef prefix */
908
+ def stripMethodPrefix (implicit ctx : Context ): Type = this match {
909
+ case tp : PolyType => tp.resType.stripMethodPrefix
910
+ case tp : AppliedTermRef => tp.resType.stripMethodPrefix
909
911
case _ => this
910
912
}
911
913
@@ -1216,26 +1218,26 @@ object Types {
1216
1218
}
1217
1219
1218
1220
/** The parameter types of a PolyType or MethodType, Empty list for others */
1219
- final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripPoly match {
1221
+ final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripMethodPrefix match {
1220
1222
case mt : MethodType => mt.paramInfos :: mt.resultType.paramInfoss
1221
1223
case _ => Nil
1222
1224
}
1223
1225
1224
1226
/** The parameter names of a PolyType or MethodType, Empty list for others */
1225
- final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripPoly match {
1227
+ final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripMethodPrefix match {
1226
1228
case mt : MethodType => mt.paramNames :: mt.resultType.paramNamess
1227
1229
case _ => Nil
1228
1230
}
1229
1231
1230
1232
1231
1233
/** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
1232
- final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripPoly match {
1234
+ final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripMethodPrefix match {
1233
1235
case mt : MethodType => mt.paramInfos
1234
1236
case _ => Nil
1235
1237
}
1236
1238
1237
1239
/** Is this either not a method at all, or a parameterless method? */
1238
- final def isParameterless (implicit ctx : Context ): Boolean = stripPoly match {
1240
+ final def isParameterless (implicit ctx : Context ): Boolean = stripMethodPrefix match {
1239
1241
case mt : MethodType => false
1240
1242
case _ => true
1241
1243
}
@@ -1246,7 +1248,7 @@ object Types {
1246
1248
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
1247
1249
* all parameter sections, the type itself for all others.
1248
1250
*/
1249
- def finalResultType (implicit ctx : Context ): Type = resultType.stripPoly match {
1251
+ def finalResultType (implicit ctx : Context ): Type = resultType.stripMethodPrefix match {
1250
1252
case mt : MethodType => mt.resultType.finalResultType
1251
1253
case _ => resultType
1252
1254
}
@@ -2169,6 +2171,53 @@ object Types {
2169
2171
apply(prefix, if (denot.symbol.exists) denot.symbol.asType else name).withDenot(denot)
2170
2172
}
2171
2173
2174
+ // --- AppliedTermRef ---------------------------------------------------------------------
2175
+
2176
+ /** A precise representation of a term-level application `fn(... args)`. **/
2177
+ abstract case class AppliedTermRef (fn : /* TermRef | AppliedTermRef*/ SingletonType , args : List [Type ])
2178
+ extends CachedProxyType with SingletonType
2179
+ {
2180
+ protected [this ] var myResType : Type = _
2181
+ def resType (implicit ctx : Context ): Type = {
2182
+ if (myResType == null )
2183
+ fn.widen match {
2184
+ case methTpe : MethodType => myResType = ctx.typer.applicationResultType(methTpe, args)
2185
+ }
2186
+ myResType
2187
+ }
2188
+
2189
+ def underlying (implicit ctx : Context ): Type = resType
2190
+
2191
+ def derivedAppliedTerm (fn : Type , args : List [Type ])(implicit ctx : Context ): Type =
2192
+ if ((this .fn eq fn) && (this .args eq args)) this
2193
+ else AppliedTermRef (fn, args)
2194
+
2195
+ override def computeHash (bs : Binders ) = doHash(bs, fn, args)
2196
+
2197
+ override def eql (that : Type ) = that match {
2198
+ case that : AppliedTermRef => (this .fn eq that.fn) && this .args.eqElements(that.args)
2199
+ case _ => false
2200
+ }
2201
+ }
2202
+
2203
+ final class CachedAppliedTermRef (fn : SingletonType , args : List [Type ]) extends AppliedTermRef (fn, args)
2204
+
2205
+ object AppliedTermRef {
2206
+ def apply (fn : Type , args : List [Type ])(implicit ctx : Context ): Type = {
2207
+ assertUnerased()
2208
+ fn.dealias match {
2209
+ case fn : TermRef => unique(new CachedAppliedTermRef (fn, args))
2210
+ case fn : AppliedTermRef => unique(new CachedAppliedTermRef (fn, args))
2211
+ case _ =>
2212
+ fn.widenDealias match {
2213
+ case methTpe : MethodType => ctx.typer.applicationResultType(methTpe, args)
2214
+ case _ : WildcardType => WildcardType
2215
+ case tp => throw new AssertionError (i " Don't know how to apply $tp. " )
2216
+ }
2217
+ }
2218
+ }
2219
+ }
2220
+
2172
2221
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
2173
2222
2174
2223
/** The type cls.this
@@ -3791,7 +3840,7 @@ object Types {
3791
3840
object SAMType {
3792
3841
def zeroParamClass (tp : Type )(implicit ctx : Context ): Type = tp match {
3793
3842
case tp : ClassInfo =>
3794
- def zeroParams (tp : Type ): Boolean = tp.stripPoly match {
3843
+ def zeroParams (tp : Type ): Boolean = tp.stripMethodPrefix match {
3795
3844
case mt : MethodType => mt.paramInfos.isEmpty && ! mt.resultType.isInstanceOf [MethodType ]
3796
3845
case et : ExprType => true
3797
3846
case _ => false
@@ -3912,6 +3961,8 @@ object Types {
3912
3961
tp.derivedSuperType(thistp, supertp)
3913
3962
protected def derivedAppliedType (tp : AppliedType , tycon : Type , args : List [Type ]): Type =
3914
3963
tp.derivedAppliedType(tycon, args)
3964
+ protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
3965
+ tp.derivedAppliedTerm(fn, args)
3915
3966
protected def derivedAndType (tp : AndType , tp1 : Type , tp2 : Type ): Type =
3916
3967
tp.derivedAndType(tp1, tp2)
3917
3968
protected def derivedOrType (tp : OrType , tp1 : Type , tp2 : Type ): Type =
@@ -3967,6 +4018,9 @@ object Types {
3967
4018
}
3968
4019
derivedAppliedType(tp, this (tp.tycon), mapArgs(tp.args, tp.typeParams))
3969
4020
4021
+ case tp : AppliedTermRef =>
4022
+ derivedAppliedTerm(tp, this (tp.fn), tp.args.mapConserve(this ))
4023
+
3970
4024
case tp : RefinedType =>
3971
4025
derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
3972
4026
@@ -4263,6 +4317,25 @@ object Types {
4263
4317
else tp.derivedAppliedType(tycon, args)
4264
4318
}
4265
4319
4320
+ override protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
4321
+ fn match {
4322
+ case Range (fnLo, fnHi) =>
4323
+ range(derivedAppliedTerm(tp, fnLo, args), derivedAppliedTerm(tp, fnHi, args))
4324
+ case _ =>
4325
+ if (fn.isBottomType) {
4326
+ fn
4327
+ } else if (args.exists(isRange)) {
4328
+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
4329
+ args foreach {
4330
+ case Range (lo, hi) => loBuf += lo; hiBuf += hi
4331
+ case arg => loBuf += arg; hiBuf += arg
4332
+ }
4333
+ range(tp.derivedAppliedTerm(fn, loBuf.toList), tp.derivedAppliedTerm(fn, hiBuf.toList))
4334
+ } else {
4335
+ tp.derivedAppliedTerm(fn, args)
4336
+ }
4337
+ }
4338
+
4266
4339
override protected def derivedAndType (tp : AndType , tp1 : Type , tp2 : Type ) =
4267
4340
if (isRange(tp1) || isRange(tp2)) range(lower(tp1) & lower(tp2), upper(tp1) & upper(tp2))
4268
4341
else tp.derivedAndType(tp1, tp2)
@@ -4353,6 +4426,9 @@ object Types {
4353
4426
}
4354
4427
foldArgs(this (x, tycon), tp.typeParams, args)
4355
4428
4429
+ case tp : AppliedTermRef =>
4430
+ foldOver(this (x, tp.fn), tp.args)
4431
+
4356
4432
case _ : BoundType | _ : ThisType => x
4357
4433
4358
4434
case tp : LambdaType =>
0 commit comments