@@ -444,9 +444,12 @@ object Parsers {
444444
445445 /** Convert tree to formal parameter
446446 */
447- def convertToParam (tree : Tree , mods : Modifiers , expected : String = " formal parameter" ): ValDef = tree match {
447+ def convertToParam (tree : Tree , mods : Modifiers , expected : String = " formal parameter" ): ValDef = tree match
448+ case param : ValDef =>
449+ param.withMods(param.mods | mods.flags)
448450 case id @ Ident (name) =>
449451 makeParameter(name.asTermName, TypeTree (), mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
452+ // the following three cases are needed only for 2.x parameters without enclosing parentheses
450453 case Typed (_, tpt : TypeBoundsTree ) =>
451454 syntaxError(s " not a legal $expected" , tree.span)
452455 makeParameter(nme.ERROR , tree, mods)
@@ -455,7 +458,6 @@ object Parsers {
455458 case _ =>
456459 syntaxError(s " not a legal $expected" , tree.span)
457460 makeParameter(nme.ERROR , tree, mods)
458- }
459461
460462 /** Convert (qual)ident to type identifier
461463 */
@@ -913,6 +915,21 @@ object Parsers {
913915 }
914916 }
915917
918+ /** When encountering a `:`, is that in the first binding of a lambda?
919+ * @pre location of the enclosing expression is `InParens`, so there is am open `(`.
920+ */
921+ def followingisLambdaParams () =
922+ val lookahead = in.LookaheadScanner ()
923+ lookahead.nextToken()
924+ while lookahead.token != RPAREN && lookahead.token != EOF do
925+ if lookahead.token == LPAREN then lookahead.skipParens()
926+ else lookahead.nextToken()
927+ lookahead.token == RPAREN
928+ && {
929+ lookahead.nextToken()
930+ lookahead.isArrow
931+ }
932+
916933 /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
917934
918935 var opStack : List [OpInfo ] = Nil
@@ -2292,7 +2309,7 @@ object Parsers {
22922309 placeholderParams = param :: placeholderParams
22932310 atSpan(start) { Ident (pname) }
22942311 case LPAREN =>
2295- atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOpt ())) }
2312+ atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOrBindings ())) }
22962313 case LBRACE | INDENT =>
22972314 canApply = false
22982315 blockExpr()
@@ -2362,7 +2379,17 @@ object Parsers {
23622379 val app = applyToClosure(t, in.offset, convertToParams(termIdent()))
23632380 simpleExprRest(app, location, canApply = true )
23642381 case _ =>
2365- t
2382+ t match
2383+ case id @ Ident (name)
2384+ if in.isColon() && location == Location .InParens && followingisLambdaParams() =>
2385+ if name.is(WildcardParamName ) then
2386+ assert(name == placeholderParams.head.name)
2387+ placeholderParams = placeholderParams.tail
2388+ atSpan(startOffset(id)) {
2389+ makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2390+ }
2391+ case _ =>
2392+ t
23662393 }
23672394 }
23682395
@@ -2396,9 +2423,20 @@ object Parsers {
23962423 }
23972424
23982425 /** ExprsInParens ::= ExprInParens {`,' ExprInParens}
2426+ * Bindings ::= Binding {`,' Binding}
23992427 */
2400- def exprsInParensOpt (): List [Tree ] =
2401- if (in.token == RPAREN ) Nil else commaSeparated(exprInParens)
2428+ def exprsInParensOrBindings (): List [Tree ] =
2429+ if in.token == RPAREN then Nil
2430+ else in.currentRegion.withCommasExpected {
2431+ var isFormalParams = false
2432+ def exprOrBinding () =
2433+ if isFormalParams then binding(Modifiers ())
2434+ else
2435+ val t = exprInParens()
2436+ if t.isInstanceOf [ValDef ] then isFormalParams = true
2437+ t
2438+ commaSeparatedRest(exprOrBinding(), exprOrBinding)
2439+ }
24022440
24032441 /** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
24042442 * | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
0 commit comments