diff options
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 37 |
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") /*<|<*/ { |