@@ -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)
@@ -457,7 +460,6 @@ object Parsers {
457460 case _ =>
458461 syntaxError(s " not a legal $expected" , tree.span)
459462 makeParameter(nme.ERROR , tree, mods)
460- }
461463
462464 /** Convert (qual)ident to type identifier
463465 */
@@ -915,6 +917,21 @@ object Parsers {
915917 }
916918 }
917919
920+ /** When encountering a `:`, is that in the first binding of a lambda?
921+ * @pre location of the enclosing expression is `InParens`, so there is am open `(`.
922+ */
923+ def followingisLambdaParams () =
924+ val lookahead = in.LookaheadScanner ()
925+ lookahead.nextToken()
926+ while lookahead.token != RPAREN && lookahead.token != EOF do
927+ if lookahead.token == LPAREN then lookahead.skipParens()
928+ else lookahead.nextToken()
929+ lookahead.token == RPAREN
930+ && {
931+ lookahead.nextToken()
932+ lookahead.isArrow
933+ }
934+
918935 /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
919936
920937 var opStack : List [OpInfo ] = Nil
@@ -2283,7 +2300,7 @@ object Parsers {
22832300 placeholderParams = param :: placeholderParams
22842301 atSpan(start) { Ident (pname) }
22852302 case LPAREN =>
2286- atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOpt ())) }
2303+ atSpan(in.offset) { makeTupleOrParens(inParens(exprsInParensOrBindings ())) }
22872304 case LBRACE | INDENT =>
22882305 canApply = false
22892306 blockExpr()
@@ -2353,7 +2370,17 @@ object Parsers {
23532370 val app = applyToClosure(t, in.offset, convertToParams(termIdent()))
23542371 simpleExprRest(app, location, canApply = true )
23552372 case _ =>
2356- t
2373+ t match
2374+ case id @ Ident (name)
2375+ if in.isColon() && location == Location .InParens && followingisLambdaParams() =>
2376+ if name.is(WildcardParamName ) then
2377+ assert(name == placeholderParams.head.name)
2378+ placeholderParams = placeholderParams.tail
2379+ atSpan(startOffset(id)) {
2380+ makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2381+ }
2382+ case _ =>
2383+ t
23572384 }
23582385 }
23592386
@@ -2387,9 +2414,20 @@ object Parsers {
23872414 }
23882415
23892416 /** ExprsInParens ::= ExprInParens {`,' ExprInParens}
2417+ * Bindings ::= Binding {`,' Binding}
23902418 */
2391- def exprsInParensOpt (): List [Tree ] =
2392- if (in.token == RPAREN ) Nil else commaSeparated(exprInParens)
2419+ def exprsInParensOrBindings (): List [Tree ] =
2420+ if in.token == RPAREN then Nil
2421+ else in.currentRegion.withCommasExpected {
2422+ var isFormalParams = false
2423+ def exprOrBinding () =
2424+ if isFormalParams then binding(Modifiers ())
2425+ else
2426+ val t = exprInParens()
2427+ if t.isInstanceOf [ValDef ] then isFormalParams = true
2428+ t
2429+ commaSeparatedRest(exprOrBinding(), exprOrBinding)
2430+ }
23932431
23942432 /** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
23952433 * | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
0 commit comments