aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Applications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-19 08:40:59 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-19 08:40:59 +0100
commit6be96724899f9c34db2e6c2617534dc9c4a15528 (patch)
treee396c405b43c6fc6f4fc8a124cb19acefb4dc755 /src/dotty/tools/dotc/typer/Applications.scala
parent56d8347bcd606443dde576480325677a89f5c809 (diff)
downloaddotty-6be96724899f9c34db2e6c2617534dc9c4a15528.tar.gz
dotty-6be96724899f9c34db2e6c2617534dc9c4a15528.tar.bz2
dotty-6be96724899f9c34db2e6c2617534dc9c4a15528.zip
Following type aliases when pattern matching.
Faced with a pattern like Apply(x, xs) we first look for an Apply object which is an extractor. If this fails, we now interprete Apply as a type. If it is a type alias which points to a class type that has a companion module, we then try that companion module as an extractor. Scala 2.x does ot that way, and it's used widely within dotty itself. Think tpd.Apply as the found object, Trees.Apply as the extractor. Also, added a fix to normalization which made normalization go deep into a method type.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 104fe0555..4202e05e1 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -333,7 +333,7 @@ trait Applications extends Compatibility { self: Typer =>
/** Subclass of Application for applicability tests with trees as arguments. */
class ApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context)
extends TestApplication(methRef, methRef, args, resultType) {
- def argType(arg: Tree): Type = normalize(arg.tpe)
+ def argType(arg: Tree): Type = normalize(arg.tpe, NoType)
def treeToArg(arg: Tree): Tree = arg
def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg)
}
@@ -546,7 +546,31 @@ trait Applications extends Compatibility { self: Typer =>
def notAnExtractor(tree: Tree) =
errorTree(tree, s"${qual.show} cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method")
- val unapply = {
+ /** If this is a term ref tree, try to typecheck with its type name.
+ * If this refers to a type alias, follow the alias, and if
+ * one finds a class, reference the class companion module.
+ */
+ def followTypeAlias(tree: untpd.Tree): untpd.Tree = {
+ tree match {
+ case tree: untpd.RefTree =>
+ val ttree = typedType(tree.withName(tree.name.toTypeName))
+ ttree.tpe match {
+ case alias: TypeRef if alias.symbol.isAliasType =>
+ companionRef(alias) match {
+ case companion: TermRef => return untpd.ref(companion)
+ case _ =>
+ }
+ case _ =>
+ }
+ case _ =>
+ }
+ untpd.EmptyTree
+ }
+
+ /** A typed qual.unappy or qual.unappySeq tree, if this typechecks.
+ * Otherwise fallBack with (maltyped) qual.unapply as argument
+ */
+ def trySelectUnapply(qual: untpd.Tree)(fallBack: Tree => Tree): Tree = {
val unappProto = new UnapplyFunProto(this)
tryEither {
implicit ctx => typedExpr(untpd.Select(qual, nme.unapply), unappProto)
@@ -555,11 +579,20 @@ trait Applications extends Compatibility { self: Typer =>
tryEither {
implicit ctx => typedExpr(untpd.Select(qual, nme.unapplySeq), unappProto) // for backwards compatibility; will be dropped
} {
- (_, _) => notAnExtractor(sel)
+ (_, _) => fallBack(sel)
}
}
}
+ /** Produce a typed qual.unappy or qual.unappySeq tree, or
+ * else if this fails follow a type alias and try again.
+ */
+ val unapply = trySelectUnapply(qual) { sel =>
+ val qual1 = followTypeAlias(qual)
+ if (qual1.isEmpty) notAnExtractor(sel)
+ else trySelectUnapply(qual1)(_ => notAnExtractor(sel))
+ }
+
def fromScala2x = unapply.symbol.exists && (unapply.symbol.owner is Scala2x)
def unapplyArgs(unapplyResult: Type)(implicit ctx: Context): List[Type] = {