aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer/Applications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-12-15 15:21:26 +0100
committerMartin Odersky <odersky@gmail.com>2016-12-15 15:21:26 +0100
commitb1553cb9c5894e2e91925a67afd2c986675e5c46 (patch)
treef9def6ae664f0df939a51b55c5283790b93a7c4d /compiler/src/dotty/tools/dotc/typer/Applications.scala
parent9bf58090c704a59d8735874c565200758bcea666 (diff)
downloaddotty-b1553cb9c5894e2e91925a67afd2c986675e5c46.tar.gz
dotty-b1553cb9c5894e2e91925a67afd2c986675e5c46.tar.bz2
dotty-b1553cb9c5894e2e91925a67afd2c986675e5c46.zip
Implement new rules for name-based pattern matching
This implements the rules laid down in #1805.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala44
1 files changed, 27 insertions, 17 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index eca4df617..d34804865 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -47,13 +47,13 @@ object Applications {
ref.info.widenExpr.dealias
}
- /** Does `tp` fit the "product match" conditions as an unapply result type?
- * This is the case of `tp` is a subtype of a ProductN class and `tp` has a
- * parameterless `isDefined` member of result type `Boolean`.
+ /** Does `tp` fit the "product match" conditions as an unapply result type
+ * for a pattern with `numArgs` subpatterns>
+ * This is the case of `tp` is a subtype of the Product<numArgs> class.
*/
- def isProductMatch(tp: Type, errorPos: Position = NoPosition)(implicit ctx: Context) =
- extractorMemberType(tp, nme.isDefined, errorPos).isRef(defn.BooleanClass) &&
- defn.isProductSubType(tp)
+ def isProductMatch(tp: Type, numArgs: Int)(implicit ctx: Context) =
+ 0 <= numArgs && numArgs <= Definitions.MaxTupleArity &&
+ tp.derivesFrom(defn.ProductNType(numArgs).typeSymbol)
/** Does `tp` fit the "get match" conditions as an unapply result type?
* This is the case of `tp` has a `get` member as well as a
@@ -82,28 +82,38 @@ object Applications {
def unapplyArgs(unapplyResult: Type, unapplyFn: Tree, args: List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = {
+ val unapplyName = unapplyFn.symbol.name
def seqSelector = defn.RepeatedParamType.appliedTo(unapplyResult.elemType :: Nil)
+ def getTp = extractorMemberType(unapplyResult, nme.get, pos)
def fail = {
- ctx.error(i"$unapplyResult is not a valid result type of an unapply method of an extractor", pos)
+ ctx.error(i"$unapplyResult is not a valid result type of an $unapplyName method of an extractor", pos)
Nil
}
- // println(s"unapply $unapplyResult ${extractorMemberType(unapplyResult, nme.isDefined)}")
- if (isProductMatch(unapplyResult))
- productSelectorTypes(unapplyResult)
- else if (isGetMatch(unapplyResult)) {
- val getTp = extractorMemberType(unapplyResult, nme.get, pos)
- if (unapplyFn.symbol.name == nme.unapplySeq) {
+ if (unapplyName == nme.unapplySeq) {
+ if (unapplyResult derivesFrom defn.SeqClass) seqSelector :: Nil
+ else if (isGetMatch(unapplyResult, pos)) {
val seqArg = boundsToHi(getTp.elemType)
if (seqArg.exists) args.map(Function.const(seqArg))
else fail
}
- else getUnapplySelectors(getTp, args, pos)
+ else fail
+ }
+ else {
+ assert(unapplyName == nme.unapply)
+ if (isProductMatch(unapplyResult, args.length))
+ productSelectorTypes(unapplyResult)
+ else if (isGetMatch(unapplyResult, pos))
+ getUnapplySelectors(getTp, args, pos)
+ else if (unapplyResult isRef defn.BooleanClass)
+ Nil
+ else if (defn.isProductSubType(unapplyResult))
+ productSelectorTypes(unapplyResult)
+ // this will cause a "wrong number of arguments in pattern" error later on,
+ // which is better than the message in `fail`.
+ else fail
}
- else if (unapplyResult derivesFrom defn.SeqClass) seqSelector :: Nil
- else if (unapplyResult isRef defn.BooleanClass) Nil
- else fail
}
def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(implicit ctx: Context): Tree =