Skip to content

Commit 203b3a9

Browse files
committed
Add syntactic sugar for polymorphic function types
Desugar the type [T_1, ..., T_M] -> (P_1, ..., P_N) => R Into scala.PolyFunction { def apply[T_1, ..., T_M](x$1: P_1, ..., x$N: P_N): R }
1 parent 8cfc30a commit 203b3a9

File tree

4 files changed

+22
-1
lines changed

4 files changed

+22
-1
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,15 @@ object desugar {
10901090
}
10911091

10921092
val desugared = tree match {
1093+
case PolyFunction(targs, body) if (ctx.mode.is(Mode.Type)) =>
1094+
// Desugar [T_1, ..., T_M] -> (P_1, ..., P_N) => R
1095+
// Into scala.PolyFunction { def apply[T_1, ..., T_M](x$1: P_1, ..., x$N: P_N): R }
1096+
val Function(vargs, resType) = body
1097+
val applyTParams = targs.asInstanceOf[List[TypeDef]]
1098+
val applyVParams = vargs.zipWithIndex.map({case (p, n) => makeSyntheticParameter(n + 1, p)})
1099+
RefinedTypeTree(ref(defn.PolyFunctionType), List(
1100+
DefDef(nme.apply, applyTParams, List(applyVParams), resType, EmptyTree)
1101+
))
10931102
case SymbolLit(str) =>
10941103
Literal(Constant(scala.Symbol(str)))
10951104
case Quote(expr) =>

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
5959
/** A function type with `implicit` or `erased` modifiers */
6060
class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers) extends Function(args, body)
6161

62+
/** A polymorphic function type */
63+
case class PolyFunction(targs: List[Tree], body: Tree) extends Tree {
64+
override def isTerm = body.isTerm
65+
override def isType = body.isType
66+
}
67+
6268
/** A function created from a wildcard expression
6369
* @param placeholderParams a list of definitions of synthetic parameters.
6470
* @param body the function body where wildcards are replaced by
@@ -436,6 +442,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
436442
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
437443
case _ => finalize(tree, untpd.Function(args, body))
438444
}
445+
def PolyFunction(tree: Tree)(targs: List[Tree], body: Tree) = tree match {
446+
case tree: PolyFunction if (targs eq tree.targs) && (body eq tree.body) => tree
447+
case _ => finalize(tree, untpd.PolyFunction(targs, body))
448+
}
439449
def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree) = tree match {
440450
case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
441451
case _ => finalize(tree, untpd.InfixOp(left, op, right))

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,8 @@ object Parsers {
792792
val tparams = typeParamClause(ParamOwner.TypeParam)
793793
if (in.token == ARROW)
794794
atPos(start, in.skipToken())(LambdaTypeTree(tparams, toplevelTyp()))
795+
else if (isIdent && in.name.toString == "->")
796+
atPos(start, in.skipToken())(PolyFunction(tparams, toplevelTyp()))
795797
else { accept(ARROW); typ() }
796798
}
797799
else infixType()

tests/run/polymorphic-functions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object Test {
2-
def test1(f: PolyFunction { def apply[T <: AnyVal](x: List[T]): List[(T, T)] }) = {
2+
def test1(f: [T <: AnyVal] -> List[T] => List[(T, T)]) = {
33
f(List(1, 2, 3))
44
}
55

0 commit comments

Comments
 (0)