diff options
author | Martin Odersky <odersky@gmail.com> | 2013-12-15 12:26:04 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-12-15 12:26:04 +0100 |
commit | 99393624e3bf001a6c20c7615ac88ef4201a93f8 (patch) | |
tree | 1f3a8800364fcfb1001b08a335acdfe8fa288c01 /src/dotty/tools/dotc/core/Types.scala | |
parent | 01db9a68e5e68f08c8236c23c905009789d51587 (diff) | |
download | dotty-99393624e3bf001a6c20c7615ac88ef4201a93f8.tar.gz dotty-99393624e3bf001a6c20c7615ac88ef4201a93f8.tar.bz2 dotty-99393624e3bf001a6c20c7615ac88ef4201a93f8.zip |
Fixes related to SAM types.
1. Changes to SAMType extractor
2. Self names are no longer members of enclosing class
3. SAM-Type closures now print with their result type.
4. refactoring newSkolemSingleon ==> narrow
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 1b05594e6..22d84c4e1 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -596,6 +596,9 @@ object Types { def underlyingIfRepeated(implicit ctx: Context): Type = this.translateParameterized(defn.RepeatedParamClass, defn.SeqClass) + /** A prefix-less termRef to a new skolem symbol that has the given type as info */ + def narrow(implicit ctx: Context): TermRef = TermRef(NoPrefix, ctx.newSkolem(this)) + // ----- Normalizing typerefs over refined types ---------------------------- /** If this is a refinement type that has a refinement for `name` (which might be followed @@ -1987,7 +1990,7 @@ object Types { /** 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 with a non-dependent method type (ExprType + * - has a single abstract method with a method type (ExprType * and PolyType not allowed!) * - can be instantiated without arguments or with just () as argument. * @@ -1995,34 +1998,50 @@ object Types { * denotation of the single abstract method as a member of the type. */ object SAMType { - def isInstantiatable(tp: Type)(implicit ctx: Context): Boolean = tp match { - case tp: TypeRef => - isInstantiatable(tp.info) + def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp match { case tp: ClassInfo => def zeroParams(tp: Type): Boolean = tp match { - case pt: PolyType => zeroParams(pt) + case pt: PolyType => zeroParams(pt.resultType) case mt: MethodType => mt.paramTypes.isEmpty && !mt.resultType.isInstanceOf[MethodType] case et: ExprType => true case _ => false } - val noParamsNeeded = (tp.cls is Trait) || zeroParams(tp.cls.primaryConstructor.info) // !!! needs to be adapted once traits have parameters - val selfTypeFeasible = tp.typeRef <:< tp.selfType - noParamsNeeded && selfTypeFeasible + if ((tp.cls is Trait) || zeroParams(tp.cls.primaryConstructor.info)) tp // !!! needs to be adapted once traits have parameters + else NoType + case tp: TypeRef => + zeroParamClass(tp.underlying) case tp: RefinedType => - isInstantiatable(tp.underlying) + zeroParamClass(tp.underlying) case tp: TypeVar => - isInstantiatable(tp.underlying) + zeroParamClass(tp.underlying) + case _ => + NoType + } + def isInstantiatable(tp: Type)(implicit ctx: Context): Boolean = zeroParamClass(tp) match { + case cinfo: ClassInfo => + val tref = tp.narrow + val selfType = cinfo.selfType.asSeenFrom(tref, cinfo.cls) + tref <:< selfType case _ => false } def unapply(tp: Type)(implicit ctx: Context): Option[SingleDenotation] = if (isInstantiatable(tp)) { val absMems = tp.abstractTermMembers + // println(s"absMems: ${absMems map (_.show) mkString ", "}") if (absMems.size == 1) absMems.head.info match { case mt: MethodType if !mt.isDependent => Some(absMems.head) case _=> None } + else if (tp isRef defn.PartialFunctionClass) + // To maintain compatibility with 2.x, we treat PartialFunction specially, + // pretending it is a SAM type. In the future it would be better to merge + // Function and PartialFunction, have Function1 contain a isDefinedAt method + // def isDefinedAt(x: T) = true + // and overwrite that method whenever the function body is a sequence of + // case clauses. + absMems.find(_.symbol.name == nme.apply) else None } else None |