@@ -1322,8 +1322,19 @@ object Parsers {
13221322 def functionRest (params : List [Tree ]): Tree =
13231323 atSpan(start, accept(ARROW )) {
13241324 val t = typ()
1325+
13251326 if (imods.isOneOf(Given | Erased )) new FunctionWithMods (params, t, imods)
1326- else Function (params, t)
1327+ else if (ctx.settings.YkindProjector .value) {
1328+ val (newParams :+ newT, tparams) = replaceKindProjectorPlaceholders(params :+ t)
1329+
1330+ if (tparams.isEmpty) {
1331+ Function (params, t)
1332+ } else {
1333+ LambdaTypeTree (tparams, Function (newParams, newT))
1334+ }
1335+ } else {
1336+ Function (params, t)
1337+ }
13271338 }
13281339 def funArgTypesRest (first : Tree , following : () => Tree ) = {
13291340 val buf = new ListBuffer [Tree ] += first
@@ -1413,6 +1424,23 @@ object Parsers {
14131424 }
14141425 }
14151426
1427+ /** Replaces kind-projector's `*` in a list of types arguments with synthetic names,
1428+ * returning the new argument list and the synthetic type definitions.
1429+ */
1430+ private def replaceKindProjectorPlaceholders (params : List [Tree ]): (List [Tree ], List [TypeDef ]) = {
1431+ val tparams = new ListBuffer [TypeDef ]
1432+
1433+ val newParams = params.map {
1434+ case Ident (tpnme.raw.STAR ) =>
1435+ val name = tpnme.syntheticTypeParamName(tparams.length)
1436+ tparams += TypeDef (name, TypeBoundsTree (EmptyTree , EmptyTree ))
1437+ Ident (name)
1438+ case other => other
1439+ }
1440+
1441+ (newParams, tparams.toList)
1442+ }
1443+
14161444 private def implicitKwPos (start : Int ): Span =
14171445 Span (start, start + nme.IMPLICITkw .asSimpleName.length)
14181446
@@ -1529,7 +1557,6 @@ object Parsers {
15291557 typeBounds().withSpan(Span (start, in.lastOffset, start))
15301558 }
15311559 else if (isIdent(nme.* ) && ctx.settings.YkindProjector .value) {
1532- syntaxError(" `*` placeholders are not implemented yet" )
15331560 typeIdent()
15341561 }
15351562 else if (isSplice)
@@ -1550,8 +1577,60 @@ object Parsers {
15501577 private def simpleTypeRest (t : Tree ): Tree = in.token match {
15511578 case HASH => simpleTypeRest(typeProjection(t))
15521579 case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
1553- AppliedTypeTree (rejectWildcardType(t), typeArgs(namedOK = false , wildOK = true )) })
1554- case _ => t
1580+ val applied = rejectWildcardType(t)
1581+ val args = typeArgs(namedOK = false , wildOK = true )
1582+
1583+ if (ctx.settings.YkindProjector .value) {
1584+ def fail (): Tree = {
1585+ syntaxError(
1586+ " λ requires a single argument of the form X => ... or (X, Y) => ..." ,
1587+ Span (t.span.start, in.lastOffset)
1588+ )
1589+ AppliedTypeTree (applied, args)
1590+ }
1591+
1592+ applied match {
1593+ case Ident (tpnme.raw.LAMBDA ) =>
1594+ args match {
1595+ case List (Function (params, body)) =>
1596+ val typeDefs = params.collect {
1597+ case Ident (name) => TypeDef (name.toTypeName, TypeBoundsTree (EmptyTree , EmptyTree ))
1598+ }
1599+ if (typeDefs.length != params.length) fail()
1600+ else LambdaTypeTree (typeDefs, body)
1601+ case _ =>
1602+ fail()
1603+ }
1604+ case _ =>
1605+ val (newArgs, tparams) = replaceKindProjectorPlaceholders(args)
1606+
1607+ if (tparams.isEmpty) {
1608+ AppliedTypeTree (applied, args)
1609+ } else {
1610+ LambdaTypeTree (tparams, AppliedTypeTree (applied, newArgs))
1611+ }
1612+ }
1613+
1614+ } else {
1615+ AppliedTypeTree (applied, args)
1616+ }
1617+ })
1618+ case _ =>
1619+ if (ctx.settings.YkindProjector .value) {
1620+ t match {
1621+ case Tuple (params) =>
1622+ val (newParams, tparams) = replaceKindProjectorPlaceholders(params)
1623+
1624+ if (tparams.isEmpty) {
1625+ t
1626+ } else {
1627+ LambdaTypeTree (tparams, Tuple (newParams))
1628+ }
1629+ case _ => t
1630+ }
1631+ } else {
1632+ t
1633+ }
15551634 }
15561635
15571636 private def typeProjection (t : Tree ): Tree = {
0 commit comments