Skip to content

Commit 4e287d5

Browse files
committed
Add isLambda... tests
Testing whether a type is (a subtype of) a Lambda class.
1 parent 96196c9 commit 4e287d5

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ object SymDenotations {
324324
final def isRefinementClass(implicit ctx: Context): Boolean =
325325
name.decode == tpnme.REFINE_CLASS
326326

327+
final def isLambdaTrait(implicit ctx: Context): Boolean =
328+
isClass && name.startsWith(tpnme.LambdaPrefix)
329+
327330
/** Is this symbol a package object or its module class? */
328331
def isPackageObject(implicit ctx: Context): Boolean = {
329332
val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import Decorators._
88
import util.Stats._
99
import util.common._
1010
import Names._
11+
import NameOps._
1112
import Flags._
13+
import StdNames.tpnme
1214
import util.Positions.Position
1315
import config.Printers._
1416
import collection.mutable
@@ -108,6 +110,41 @@ class TypeApplications(val self: Type) extends AnyVal {
108110
def uninstantiatedTypeParams(implicit ctx: Context): List[TypeSymbol] =
109111
typeParams filter (tparam => self.member(tparam.name).symbol == tparam)
110112

113+
/** If type `tp` is equal, aliased-to, or upperbounded-by a type of the form
114+
* `LambdaXYZ { ... }`, the class symbol of that type, otherwise NoSymbol.
115+
* @param forcing if set, might force completion. If not, never forces
116+
* but returns NoSymbol when it would have to otherwise.
117+
*/
118+
def LambdaClass(forcing: Boolean)(implicit ctx: Context): Symbol = ctx.traceIndented(i"LambdaClass($self)", hk) { self.stripTypeVar match {
119+
case self: TypeRef =>
120+
val sym = self.symbol
121+
if (sym.isLambdaTrait) sym
122+
else if (sym.isClass || sym.isCompleting && !forcing) NoSymbol
123+
else self.info.LambdaClass(forcing)
124+
case self: TermRef =>
125+
NoSymbol
126+
case self: TypeProxy =>
127+
self.underlying.LambdaClass(forcing)
128+
case _ =>
129+
NoSymbol
130+
}}
131+
132+
/** Is type `tp` equal, aliased-to, or upperbounded-by a type of the form
133+
* `LambdaXYZ { ... }`?
134+
*/
135+
def isLambda(implicit ctx: Context): Boolean =
136+
LambdaClass(forcing = true).exists
137+
138+
/** Same is `isLambda`, except that symbol denotations are not forced
139+
* Symbols in completion count as not lambdas.
140+
*/
141+
def isSafeLambda(implicit ctx: Context): Boolean =
142+
LambdaClass(forcing = false).exists
143+
144+
/** Is type `tp` a Lambda with all Arg$ fields fully instantiated? */
145+
def isInstantiatedLambda(tp: Type)(implicit ctx: Context): Boolean =
146+
tp.isSafeLambda && tp.typeParams.forall(_.name == tpnme.Apply)
147+
111148
/** Encode the type resulting from applying this type to given arguments */
112149
final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ {
113150

0 commit comments

Comments
 (0)