diff options
author | Martin Odersky <odersky@gmail.com> | 2013-07-15 12:50:34 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-07-15 12:50:34 +0200 |
commit | 9e9eb7e126122e122118018fa6d0383156fe9ab5 (patch) | |
tree | 944d49bf706711a4451a8009c6d6d81567182c35 /src/dotty | |
parent | e67de603b531ad268b906d77e900425e917c2a08 (diff) | |
download | dotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.tar.gz dotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.tar.bz2 dotty-9e9eb7e126122e122118018fa6d0383156fe9ab5.zip |
Added provisional extractor for SAM types
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 42 |
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 => |