@@ -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
@@ -282,14 +283,14 @@ object Types {
282
283
/** Is this the type of a method that has a repeated parameter type as
283
284
* last parameter type?
284
285
*/
285
- def isVarArgsMethod (implicit ctx : Context ): Boolean = stripPoly match {
286
+ def isVarArgsMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
286
287
case mt : MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam
287
288
case _ => false
288
289
}
289
290
290
291
/** Is this the type of a method with a leading empty parameter list?
291
292
*/
292
- def isNullaryMethod (implicit ctx : Context ): Boolean = stripPoly match {
293
+ def isNullaryMethod (implicit ctx : Context ): Boolean = stripMethodPrefix match {
293
294
case MethodType (Nil ) => true
294
295
case _ => false
295
296
}
@@ -899,9 +900,10 @@ object Types {
899
900
*/
900
901
def stripAnnots (implicit ctx : Context ): Type = this
901
902
902
- /** Strip PolyType prefix */
903
- def stripPoly (implicit ctx : Context ): Type = this match {
904
- case tp : PolyType => tp.resType.stripPoly
903
+ /** Strip PolyType and AppliedTermRef prefix */
904
+ def stripMethodPrefix (implicit ctx : Context ): Type = this match {
905
+ case tp : PolyType => tp.resType.stripMethodPrefix
906
+ case tp : AppliedTermRef => tp.resType.stripMethodPrefix
905
907
case _ => this
906
908
}
907
909
@@ -1212,26 +1214,26 @@ object Types {
1212
1214
}
1213
1215
1214
1216
/** The parameter types of a PolyType or MethodType, Empty list for others */
1215
- final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripPoly match {
1217
+ final def paramInfoss (implicit ctx : Context ): List [List [Type ]] = stripMethodPrefix match {
1216
1218
case mt : MethodType => mt.paramInfos :: mt.resultType.paramInfoss
1217
1219
case _ => Nil
1218
1220
}
1219
1221
1220
1222
/** The parameter names of a PolyType or MethodType, Empty list for others */
1221
- final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripPoly match {
1223
+ final def paramNamess (implicit ctx : Context ): List [List [TermName ]] = stripMethodPrefix match {
1222
1224
case mt : MethodType => mt.paramNames :: mt.resultType.paramNamess
1223
1225
case _ => Nil
1224
1226
}
1225
1227
1226
1228
1227
1229
/** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
1228
- final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripPoly match {
1230
+ final def firstParamTypes (implicit ctx : Context ): List [Type ] = stripMethodPrefix match {
1229
1231
case mt : MethodType => mt.paramInfos
1230
1232
case _ => Nil
1231
1233
}
1232
1234
1233
1235
/** Is this either not a method at all, or a parameterless method? */
1234
- final def isParameterless (implicit ctx : Context ): Boolean = stripPoly match {
1236
+ final def isParameterless (implicit ctx : Context ): Boolean = stripMethodPrefix match {
1235
1237
case mt : MethodType => false
1236
1238
case _ => true
1237
1239
}
@@ -1242,7 +1244,7 @@ object Types {
1242
1244
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
1243
1245
* all parameter sections, the type itself for all others.
1244
1246
*/
1245
- def finalResultType (implicit ctx : Context ): Type = resultType.stripPoly match {
1247
+ def finalResultType (implicit ctx : Context ): Type = resultType.stripMethodPrefix match {
1246
1248
case mt : MethodType => mt.resultType.finalResultType
1247
1249
case _ => resultType
1248
1250
}
@@ -2171,6 +2173,55 @@ object Types {
2171
2173
apply(prefix, if (denot.symbol.exists) denot.symbol.asType else name).withDenot(denot)
2172
2174
}
2173
2175
2176
+ // --- AppliedTermRef ---------------------------------------------------------------------
2177
+
2178
+ /** An opaque representation of a term-level application. **/
2179
+ abstract case class AppliedTermRef (fn : /* TermRef | AppliedTermRef*/ SingletonType , args : List [Type ])
2180
+ extends CachedProxyType with SingletonType
2181
+ {
2182
+ protected [this ] var myResType : Type = _
2183
+ def resType (implicit ctx : Context ): Type = {
2184
+ if (myResType == null )
2185
+ // FIXME(gsps): Sometimes TermRef(TermParamRef(<fun>, 1), +) might not have a denot, e.g., when calling
2186
+ // def add[X<:Int, Y<:Int, Z<:Int](x: X, y: Y, z: {x + y}): z.type = z
2187
+ fn.widen match {
2188
+ case methTpe : MethodType => myResType = ctx.typer.applicationResultType(methTpe, args)
2189
+ }
2190
+ myResType
2191
+ }
2192
+
2193
+ def underlying (implicit ctx : Context ): Type = resType
2194
+
2195
+ def derivedAppliedTerm (fn : Type , args : List [Type ])(implicit ctx : Context ): Type =
2196
+ if ((this .fn eq fn) && (this .args eq args)) this
2197
+ else AppliedTermRef (fn, args)
2198
+
2199
+ override def computeHash (bs : Binders ) = doHash(bs, fn, args)
2200
+
2201
+ override def eql (that : Type ) = that match {
2202
+ case that : AppliedTermRef => (this .fn eq that.fn) && this .args.eqElements(that.args)
2203
+ case _ => false
2204
+ }
2205
+ }
2206
+
2207
+ final class CachedAppliedTermRef (fn : SingletonType , args : List [Type ]) extends AppliedTermRef (fn, args)
2208
+
2209
+ object AppliedTermRef {
2210
+ def apply (fn : Type , args : List [Type ])(implicit ctx : Context ): Type = {
2211
+ assertUnerased()
2212
+ fn.dealias match {
2213
+ case fn : TermRef => unique(new CachedAppliedTermRef (fn, args))
2214
+ case fn : AppliedTermRef => unique(new CachedAppliedTermRef (fn, args))
2215
+ case _ =>
2216
+ fn.widenDealias match {
2217
+ case methTpe : MethodType => ctx.typer.applicationResultType(methTpe, args) // TODO(gsps): Check length?
2218
+ case _ : WildcardType => WildcardType
2219
+ case tp => throw new AssertionError (i " Don't know how to apply $tp. " )
2220
+ }
2221
+ }
2222
+ }
2223
+ }
2224
+
2174
2225
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
2175
2226
2176
2227
/** The type cls.this
@@ -3791,7 +3842,7 @@ object Types {
3791
3842
object SAMType {
3792
3843
def zeroParamClass (tp : Type )(implicit ctx : Context ): Type = tp match {
3793
3844
case tp : ClassInfo =>
3794
- def zeroParams (tp : Type ): Boolean = tp.stripPoly match {
3845
+ def zeroParams (tp : Type ): Boolean = tp.stripMethodPrefix match {
3795
3846
case mt : MethodType => mt.paramInfos.isEmpty && ! mt.resultType.isInstanceOf [MethodType ]
3796
3847
case et : ExprType => true
3797
3848
case _ => false
@@ -3877,6 +3928,8 @@ object Types {
3877
3928
tp.derivedSuperType(thistp, supertp)
3878
3929
protected def derivedAppliedType (tp : AppliedType , tycon : Type , args : List [Type ]): Type =
3879
3930
tp.derivedAppliedType(tycon, args)
3931
+ protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
3932
+ tp.derivedAppliedTerm(fn, args)
3880
3933
protected def derivedAndType (tp : AndType , tp1 : Type , tp2 : Type ): Type =
3881
3934
tp.derivedAndType(tp1, tp2)
3882
3935
protected def derivedOrType (tp : OrType , tp1 : Type , tp2 : Type ): Type =
@@ -3932,6 +3985,9 @@ object Types {
3932
3985
}
3933
3986
derivedAppliedType(tp, this (tp.tycon), mapArgs(tp.args, tp.typeParams))
3934
3987
3988
+ case tp : AppliedTermRef =>
3989
+ derivedAppliedTerm(tp, this (tp.fn), tp.args.mapConserve(this ))
3990
+
3935
3991
case tp : RefinedType =>
3936
3992
derivedRefinedType(tp, this (tp.parent), this (tp.refinedInfo))
3937
3993
@@ -4228,6 +4284,25 @@ object Types {
4228
4284
else tp.derivedAppliedType(tycon, args)
4229
4285
}
4230
4286
4287
+ override protected def derivedAppliedTerm (tp : AppliedTermRef , fn : Type , args : List [Type ]): Type =
4288
+ fn match {
4289
+ case Range (fnLo, fnHi) =>
4290
+ range(derivedAppliedTerm(tp, fnLo, args), derivedAppliedTerm(tp, fnHi, args))
4291
+ case _ =>
4292
+ if (fn.isBottomType) {
4293
+ fn
4294
+ } else if (args.exists(isRange)) {
4295
+ val loBuf, hiBuf = new mutable.ListBuffer [Type ]
4296
+ args foreach {
4297
+ case Range (lo, hi) => loBuf += lo; hiBuf += hi
4298
+ case arg => loBuf += arg; hiBuf += arg
4299
+ }
4300
+ range(tp.derivedAppliedTerm(fn, loBuf.toList), tp.derivedAppliedTerm(fn, hiBuf.toList))
4301
+ } else {
4302
+ tp.derivedAppliedTerm(fn, args)
4303
+ }
4304
+ }
4305
+
4231
4306
override protected def derivedAndType (tp : AndType , tp1 : Type , tp2 : Type ) =
4232
4307
if (isRange(tp1) || isRange(tp2)) range(lower(tp1) & lower(tp2), upper(tp1) & upper(tp2))
4233
4308
else tp.derivedAndType(tp1, tp2)
@@ -4318,6 +4393,9 @@ object Types {
4318
4393
}
4319
4394
foldArgs(this (x, tycon), tp.typeParams, args)
4320
4395
4396
+ case tp : AppliedTermRef =>
4397
+ foldOver(this (x, tp.fn), tp.args)
4398
+
4321
4399
case _ : BoundType | _ : ThisType => x
4322
4400
4323
4401
case tp : LambdaType =>
0 commit comments