@@ -73,6 +73,9 @@ object Parsers {
7373 enum ParseKind :
7474 case Expr , Type , Pattern
7575
76+ enum IntoOK :
77+ case Yes , No , Nested
78+
7679 type StageKind = Int
7780 object StageKind {
7881 val None = 0
@@ -1484,7 +1487,7 @@ object Parsers {
14841487 /** Same as [[typ ]], but if this results in a wildcard it emits a syntax error and
14851488 * returns a tree for type `Any` instead.
14861489 */
1487- def toplevelTyp (): Tree = rejectWildcardType(typ())
1490+ def toplevelTyp (intoOK : IntoOK = IntoOK . No ): Tree = rejectWildcardType(typ(intoOK ))
14881491
14891492 private def getFunction (tree : Tree ): Option [Function ] = tree match {
14901493 case Parens (tree1) => getFunction(tree1)
@@ -1535,12 +1538,21 @@ object Parsers {
15351538 * | `(' [ FunArgType {`,' FunArgType } ] `)'
15361539 * | '(' [ TypedFunParam {',' TypedFunParam } ')'
15371540 * MatchType ::= InfixType `match` <<< TypeCaseClauses >>>
1541+ * IntoType ::= [‘into’] IntoTargetType
1542+ * | ‘( IntoType ‘)’
1543+ * IntoTargetType ::= Type
1544+ * | FunTypeArgs (‘=>’ | ‘?=>’) IntoType
15381545 */
1539- def typ (): Tree =
1546+ def typ (intoOK : IntoOK = IntoOK . No ): Tree =
15401547 val start = in.offset
15411548 var imods = Modifiers ()
15421549 val erasedArgs : ListBuffer [Boolean ] = ListBuffer ()
15431550
1551+ def nestedIntoOK (token : Int ) =
1552+ if token == TLARROW then IntoOK .No
1553+ else if intoOK == IntoOK .Nested then IntoOK .Yes
1554+ else intoOK
1555+
15441556 def functionRest (params : List [Tree ]): Tree =
15451557 val paramSpan = Span (start, in.lastOffset)
15461558 atSpan(start, in.offset) {
@@ -1569,8 +1581,9 @@ object Parsers {
15691581 else
15701582 accept(ARROW )
15711583
1584+ def resType () = typ(nestedIntoOK(token))
15721585 val resultType =
1573- if isPure then capturesAndResult(typ ) else typ ()
1586+ if isPure then capturesAndResult(resType ) else resType ()
15741587 if token == TLARROW then
15751588 for case ValDef (_, tpt, _) <- params do
15761589 if isByNameType(tpt) then
@@ -1605,6 +1618,12 @@ object Parsers {
16051618 syntaxError(ErasedTypesCanOnlyBeFunctionTypes (), implicitKwPos(start))
16061619 t
16071620
1621+ def isIntoPrefix : Boolean =
1622+ intoOK == IntoOK .Yes
1623+ && in.isIdent(nme.into)
1624+ && in.featureEnabled(Feature .into)
1625+ && canStartTypeTokens.contains(in.lookahead.token)
1626+
16081627 var isValParamList = false
16091628 if in.token == LPAREN then
16101629 in.nextToken()
@@ -1635,17 +1654,36 @@ object Parsers {
16351654 funArgType()
16361655 commaSeparatedRest(t, funArg)
16371656 accept(RPAREN )
1657+
1658+ val intoAllowed =
1659+ intoOK == IntoOK .Yes
1660+ && args.lengthCompare(1 ) == 0
1661+ && (! canFollowSimpleTypeTokens.contains(in.token) || followingIsVararg())
1662+ val byNameAllowed = in.isArrow || isPureArrow
1663+
1664+ def sanitize (arg : Tree ): Tree = arg match
1665+ case ByNameTypeTree (t) if ! byNameAllowed =>
1666+ syntaxError(ByNameParameterNotSupported (t), t.span)
1667+ t
1668+ case PrefixOp (id @ Ident (tpnme.into), t) if ! intoAllowed =>
1669+ syntaxError(em " no `into` modifier allowed here " , id.span)
1670+ t
1671+ case Parens (t) =>
1672+ cpy.Parens (arg)(sanitize(t))
1673+ case arg : FunctionWithMods =>
1674+ val body1 = sanitize(arg.body)
1675+ if body1 eq arg.body then arg
1676+ else FunctionWithMods (arg.args, body1, arg.mods, arg.erasedParams).withSpan(arg.span)
1677+ case Function (args, res) if ! intoAllowed =>
1678+ cpy.Function (arg)(args, sanitize(res))
1679+ case arg =>
1680+ arg
1681+
1682+ val args1 = args.mapConserve(sanitize)
16381683 if isValParamList || in.isArrow || isPureArrow then
16391684 functionRest(args)
16401685 else
1641- val args1 = args.mapConserve: t =>
1642- if isByNameType(t) then
1643- syntaxError(ByNameParameterNotSupported (t), t.span)
1644- stripByNameType(t)
1645- else
1646- t
1647- val tuple = atSpan(start):
1648- makeTupleOrParens(args1)
1686+ val tuple = atSpan(start)(makeTupleOrParens(args1))
16491687 typeRest :
16501688 infixTypeRest :
16511689 refinedTypeRest :
@@ -1660,7 +1698,7 @@ object Parsers {
16601698 LambdaTypeTree (tparams, toplevelTyp())
16611699 else if in.token == ARROW || isPureArrow(nme.PUREARROW ) then
16621700 val arrowOffset = in.skipToken()
1663- val body = toplevelTyp()
1701+ val body = toplevelTyp(nestedIntoOK(in.token) )
16641702 atSpan(start, arrowOffset):
16651703 getFunction(body) match
16661704 case Some (f) =>
@@ -1673,6 +1711,8 @@ object Parsers {
16731711 typ()
16741712 else if in.token == INDENT then
16751713 enclosed(INDENT , typ())
1714+ else if isIntoPrefix then
1715+ PrefixOp (typeIdent(), typ(IntoOK .Nested ))
16761716 else
16771717 typeRest(infixType())
16781718 end typ
@@ -2047,18 +2087,13 @@ object Parsers {
20472087 else
20482088 core()
20492089
2050- private def maybeInto (tp : () => Tree ) =
2051- if in.isIdent(nme.into)
2052- && in.featureEnabled(Feature .into)
2053- && canStartTypeTokens.contains(in.lookahead.token)
2054- then atSpan(in.skipToken()) { Into (tp()) }
2055- else tp()
2056-
20572090 /** FunArgType ::= Type
20582091 * | `=>' Type
20592092 * | `->' [CaptureSet] Type
20602093 */
2061- val funArgType : () => Tree = () => paramTypeOf(typ)
2094+ val funArgType : () => Tree =
2095+ () => paramTypeOf(() => typ(IntoOK .Yes ))
2096+ // We allow intoOK and filter out afterwards in typ()
20622097
20632098 /** ParamType ::= ParamValueType
20642099 * | `=>' ParamValueType
@@ -2067,15 +2102,21 @@ object Parsers {
20672102 def paramType (): Tree = paramTypeOf(paramValueType)
20682103
20692104 /** ParamValueType ::= Type [`*']
2105+ * | IntoType
2106+ * | ‘(’ IntoType ‘)’ `*'
20702107 */
2071- def paramValueType (): Tree = {
2072- val t = maybeInto(toplevelTyp)
2073- if (isIdent(nme.raw.STAR )) {
2108+ def paramValueType (): Tree =
2109+ val t = toplevelTyp(IntoOK .Yes )
2110+ if isIdent(nme.raw.STAR ) then
2111+ if ! t.isInstanceOf [Parens ] && isInto(t) then
2112+ syntaxError(
2113+ em """ `*` cannot directly follow `into` parameter
2114+ |the `into` parameter needs to be put in parentheses """ ,
2115+ in.offset)
20742116 in.nextToken()
2075- atSpan(startOffset(t)) { PostfixOp (t, Ident (tpnme.raw. STAR )) }
2076- }
2117+ atSpan(startOffset(t)):
2118+ PostfixOp (t, Ident (tpnme.raw. STAR ))
20772119 else t
2078- }
20792120
20802121 /** TypeArgs ::= `[' Type {`,' Type} `]'
20812122 * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]'
@@ -3315,7 +3356,7 @@ object Parsers {
33153356 /** ContextTypes ::= FunArgType {‘,’ FunArgType}
33163357 */
33173358 def contextTypes (paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3318- val tps = commaSeparated(() => paramTypeOf(toplevelTyp))
3359+ val tps = commaSeparated(() => paramTypeOf(() => toplevelTyp() ))
33193360 var counter = numLeadParams
33203361 def nextIdx = { counter += 1 ; counter }
33213362 val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
0 commit comments