aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-07-15 12:50:34 +0200
committerMartin Odersky <odersky@gmail.com>2013-07-15 12:50:34 +0200
commit9e9eb7e126122e122118018fa6d0383156fe9ab5 (patch)
tree944d49bf706711a4451a8009c6d6d81567182c35 /src/dotty/tools/dotc
parente67de603b531ad268b906d77e900425e917c2a08 (diff)
downloaddotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.tar.gz
dotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.tar.bz2
dotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.zip
Added provisional extractor for SAM types
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 71b15f98a..508bf53b0 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -546,7 +546,7 @@ object Types {
/** The parameter types of a PolyType or MethodType, Empty list for others */
final def paramTypess: List[List[Type]] = this match {
case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
- case pt: PolyType => pt.paramTypess
+ case pt: PolyType => pt.resultType.paramTypess
case _ => Nil
}
/* Not sure whether we'll need this
@@ -1763,6 +1763,46 @@ object Types {
case object WildcardType extends UncachedGroundType
+ /** An extractor for single abstract method types.
+ * A type is a SAM type if it is a reference to a class or trait, which
+ *
+ * - has a single abstract method
+ * - can be instantiated without arguments or with just () as argument.
+ */
+ object SAMType {
+ def isInstantiatable(tp: Type)(implicit ctx: Context): Boolean = tp match {
+ case tp: TypeRef =>
+ isInstantiatable(tp.info)
+ case tp: ClassInfo =>
+ def zeroParams(tp: Type): Boolean = tp match {
+ case pt: PolyType => zeroParams(pt)
+ case mt: MethodType => mt.paramTypess.isEmpty && !mt.resultType.isInstanceOf[MethodType]
+ case et: ExprType => true
+ case _ => false
+ }
+ val noParamsNeeded = (tp.cls is Trait) || zeroParams(tp.cls.primaryConstructor.info)
+ val selfTypeFeasible = tp.typeConstructor <:< tp.selfType
+ noParamsNeeded && selfTypeFeasible
+ case tp: RefinedType =>
+ isInstantiatable(tp.underlying)
+ case tp: TypeVar =>
+ isInstantiatable(tp.thisInstance)
+ case _ =>
+ false
+ }
+ def unapply(tp: Type)(implicit ctx: Context): Option[(SingleDenotation, List[Type], Type)] =
+ if (isInstantiatable(tp)) {
+ val absMems = tp.abstractTermMembers
+ if (absMems.size == 1)
+ absMems.head.info match {
+ case mt: MethodType if !mt.isDependent => Some((absMems.head, mt.paramTypes, mt.resultType))
+ case _=> None
+ }
+ else None
+ }
+ else None
+ }
+
// ----- TypeMaps --------------------------------------------------------------------
abstract class TypeMap(implicit ctx: Context) extends (Type => Type) { thisMap =>