aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala3
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala37
2 files changed, 40 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 606966be9..46484e6cc 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -324,6 +324,9 @@ object SymDenotations {
final def isRefinementClass(implicit ctx: Context): Boolean =
name.decode == tpnme.REFINE_CLASS
+ final def isLambdaTrait(implicit ctx: Context): Boolean =
+ isClass && name.startsWith(tpnme.LambdaPrefix)
+
/** Is this symbol a package object or its module class? */
def isPackageObject(implicit ctx: Context): Boolean = {
val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index c4845a249..428178b81 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -8,7 +8,9 @@ import Decorators._
import util.Stats._
import util.common._
import Names._
+import NameOps._
import Flags._
+import StdNames.tpnme
import util.Positions.Position
import config.Printers._
import collection.mutable
@@ -108,6 +110,41 @@ class TypeApplications(val self: Type) extends AnyVal {
def uninstantiatedTypeParams(implicit ctx: Context): List[TypeSymbol] =
typeParams filter (tparam => self.member(tparam.name).symbol == tparam)
+ /** If type `tp` is equal, aliased-to, or upperbounded-by a type of the form
+ * `LambdaXYZ { ... }`, the class symbol of that type, otherwise NoSymbol.
+ * @param forcing if set, might force completion. If not, never forces
+ * but returns NoSymbol when it would have to otherwise.
+ */
+ def LambdaClass(forcing: Boolean)(implicit ctx: Context): Symbol = ctx.traceIndented(i"LambdaClass($self)", hk) { self.stripTypeVar match {
+ case self: TypeRef =>
+ val sym = self.symbol
+ if (sym.isLambdaTrait) sym
+ else if (sym.isClass || sym.isCompleting && !forcing) NoSymbol
+ else self.info.LambdaClass(forcing)
+ case self: TermRef =>
+ NoSymbol
+ case self: TypeProxy =>
+ self.underlying.LambdaClass(forcing)
+ case _ =>
+ NoSymbol
+ }}
+
+ /** Is type `tp` equal, aliased-to, or upperbounded-by a type of the form
+ * `LambdaXYZ { ... }`?
+ */
+ def isLambda(implicit ctx: Context): Boolean =
+ LambdaClass(forcing = true).exists
+
+ /** Same is `isLambda`, except that symbol denotations are not forced
+ * Symbols in completion count as not lambdas.
+ */
+ def isSafeLambda(implicit ctx: Context): Boolean =
+ LambdaClass(forcing = false).exists
+
+ /** Is type `tp` a Lambda with all Arg$ fields fully instantiated? */
+ def isInstantiatedLambda(tp: Type)(implicit ctx: Context): Boolean =
+ tp.isSafeLambda && tp.typeParams.forall(_.name == tpnme.Apply)
+
/** Encode the type resulting from applying this type to given arguments */
final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ {