aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-10-31 12:58:01 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-16 15:23:43 +0100
commit29104c9755a9d6393959a416650422b84f0957f2 (patch)
tree19f844e71f9904c19714f4cab8c93fffc97db437 /src/dotty/tools/dotc/typer/Typer.scala
parent5e8023335e641c9c05c6517a82764571e7ef6386 (diff)
downloaddotty-29104c9755a9d6393959a416650422b84f0957f2.tar.gz
dotty-29104c9755a9d6393959a416650422b84f0957f2.tar.bz2
dotty-29104c9755a9d6393959a416650422b84f0957f2.zip
Auto-uncurry n-ary functions.
Implements SIP #897.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala56
1 files changed, 37 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 6a2ff30fa..784702dba 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -611,26 +611,44 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (protoFormals.length == params.length) protoFormals(i)
else errorType(i"wrong number of parameters, expected: ${protoFormals.length}", tree.pos)
- val inferredParams: List[untpd.ValDef] =
- for ((param, i) <- params.zipWithIndex) yield
- if (!param.tpt.isEmpty) param
- else cpy.ValDef(param)(
- tpt = untpd.TypeTree(
- inferredParamType(param, protoFormal(i)).underlyingIfRepeated(isJava = false)))
-
- // Define result type of closure as the expected type, thereby pushing
- // down any implicit searches. We do this even if the expected type is not fully
- // defined, which is a bit of a hack. But it's needed to make the following work
- // (see typers.scala and printers/PlainPrinter.scala for examples).
- //
- // def double(x: Char): String = s"$x$x"
- // "abc" flatMap double
- //
- val resultTpt = protoResult match {
- case WildcardType(_) => untpd.TypeTree()
- case _ => untpd.TypeTree(protoResult)
+ /** Is `formal` a product type which is elementwise compatible with `params`? */
+ def ptIsCorrectProduct(formal: Type) = {
+ val pclass = defn.ProductNClass(params.length)
+ isFullyDefined(formal, ForceDegree.noBottom) &&
+ formal.derivesFrom(pclass) &&
+ formal.baseArgTypes(pclass).corresponds(params) {
+ (argType, param) =>
+ param.tpt.isEmpty || isCompatible(argType, typedAheadType(param.tpt).tpe)
+ }
}
- typed(desugar.makeClosure(inferredParams, fnBody, resultTpt), pt)
+
+ val desugared =
+ if (protoFormals.length == 1 && params.length != 1 && ptIsCorrectProduct(protoFormals.head)) {
+ desugar.makeUnaryCaseLambda(params, fnBody)
+ }
+ else {
+ val inferredParams: List[untpd.ValDef] =
+ for ((param, i) <- params.zipWithIndex) yield
+ if (!param.tpt.isEmpty) param
+ else cpy.ValDef(param)(
+ tpt = untpd.TypeTree(
+ inferredParamType(param, protoFormal(i)).underlyingIfRepeated(isJava = false)))
+
+ // Define result type of closure as the expected type, thereby pushing
+ // down any implicit searches. We do this even if the expected type is not fully
+ // defined, which is a bit of a hack. But it's needed to make the following work
+ // (see typers.scala and printers/PlainPrinter.scala for examples).
+ //
+ // def double(x: Char): String = s"$x$x"
+ // "abc" flatMap double
+ //
+ val resultTpt = protoResult match {
+ case WildcardType(_) => untpd.TypeTree()
+ case _ => untpd.TypeTree(protoResult)
+ }
+ desugar.makeClosure(inferredParams, fnBody, resultTpt)
+ }
+ typed(desugared, pt)
}
}