@@ -1358,8 +1358,15 @@ object Parsers {
13581358 def functionRest (params : List [Tree ]): Tree =
13591359 atSpan(start, accept(ARROW )) {
13601360 val t = typ()
1361+
13611362 if (imods.isOneOf(Given | Erased )) new FunctionWithMods (params, t, imods)
1362- else Function (params, t)
1363+ else if (ctx.settings.YkindProjector .value) {
1364+ val (newParams :+ newT, tparams) = replaceKindProjectorPlaceholders(params :+ t)
1365+
1366+ lambdaAbstract(tparams, Function (newParams, newT))
1367+ } else {
1368+ Function (params, t)
1369+ }
13631370 }
13641371 def funArgTypesRest (first : Tree , following : () => Tree ) = {
13651372 val buf = new ListBuffer [Tree ] += first
@@ -1449,6 +1456,26 @@ object Parsers {
14491456 }
14501457 }
14511458
1459+ private def makeKindProjectorTypeDef (name : TypeName ): TypeDef =
1460+ TypeDef (name, TypeBoundsTree (EmptyTree , EmptyTree )).withFlags(Param )
1461+
1462+ /** Replaces kind-projector's `*` in a list of types arguments with synthetic names,
1463+ * returning the new argument list and the synthetic type definitions.
1464+ */
1465+ private def replaceKindProjectorPlaceholders (params : List [Tree ]): (List [Tree ], List [TypeDef ]) = {
1466+ val tparams = new ListBuffer [TypeDef ]
1467+
1468+ val newParams = params.mapConserve {
1469+ case param @ Ident (tpnme.raw.STAR ) =>
1470+ val name = WildcardParamName .fresh().toTypeName
1471+ tparams += makeKindProjectorTypeDef(name)
1472+ Ident (name)
1473+ case other => other
1474+ }
1475+
1476+ (newParams, tparams.toList)
1477+ }
1478+
14521479 private def implicitKwPos (start : Int ): Span =
14531480 Span (start, start + nme.IMPLICITkw .asSimpleName.length)
14541481
@@ -1565,7 +1592,6 @@ object Parsers {
15651592 typeBounds().withSpan(Span (start, in.lastOffset, start))
15661593 }
15671594 else if (isIdent(nme.* ) && ctx.settings.YkindProjector .value) {
1568- syntaxError(" `*` placeholders are not implemented yet" )
15691595 typeIdent()
15701596 }
15711597 else if (isSplice)
@@ -1586,8 +1612,56 @@ object Parsers {
15861612 private def simpleTypeRest (t : Tree ): Tree = in.token match {
15871613 case HASH => simpleTypeRest(typeProjection(t))
15881614 case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
1589- AppliedTypeTree (rejectWildcardType(t), typeArgs(namedOK = false , wildOK = true )) })
1590- case _ => t
1615+ val applied = rejectWildcardType(t)
1616+ val args = typeArgs(namedOK = false , wildOK = true )
1617+
1618+ if (ctx.settings.YkindProjector .value) {
1619+ def fail (): Tree = {
1620+ syntaxError(
1621+ " λ requires a single argument of the form X => ... or (X, Y) => ..." ,
1622+ Span (t.span.start, in.lastOffset)
1623+ )
1624+ AppliedTypeTree (applied, args)
1625+ }
1626+
1627+ applied match {
1628+ case Ident (tpnme.raw.LAMBDA ) =>
1629+ args match {
1630+ case List (Function (params, body)) =>
1631+ val typeDefs = params.collect {
1632+ case param @ Ident (name) => makeKindProjectorTypeDef(name.toTypeName).withSpan(param.span)
1633+ }
1634+ if (typeDefs.length != params.length) fail()
1635+ else LambdaTypeTree (typeDefs, body)
1636+ case _ =>
1637+ fail()
1638+ }
1639+ case _ =>
1640+ val (newArgs, tparams) = replaceKindProjectorPlaceholders(args)
1641+
1642+ lambdaAbstract(tparams, AppliedTypeTree (applied, newArgs))
1643+ }
1644+
1645+ } else {
1646+ AppliedTypeTree (applied, args)
1647+ }
1648+ })
1649+ case _ =>
1650+ if (ctx.settings.YkindProjector .value) {
1651+ t match {
1652+ case Tuple (params) =>
1653+ val (newParams, tparams) = replaceKindProjectorPlaceholders(params)
1654+
1655+ if (tparams.isEmpty) {
1656+ t
1657+ } else {
1658+ LambdaTypeTree (tparams, Tuple (newParams))
1659+ }
1660+ case _ => t
1661+ }
1662+ } else {
1663+ t
1664+ }
15911665 }
15921666
15931667 private def typeProjection (t : Tree ): Tree = {
0 commit comments