Skip to content

Commit bb0a9a7

Browse files
authored
Merge pull request #12280 from dotty-staging/fix-12277
Allow braces just on the outside of polymorphic lambdas
2 parents 311dc17 + b35b348 commit bb0a9a7

File tree

5 files changed

+61
-40
lines changed

5 files changed

+61
-40
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,13 +1838,15 @@ object Parsers {
18381838
t
18391839

18401840
/** Expr ::= [`implicit'] FunParams (‘=>’ | ‘?=>’) Expr
1841+
* | HkTypeParamClause ‘=>’ Expr
18411842
* | Expr1
18421843
* FunParams ::= Bindings
18431844
* | id
18441845
* | `_'
18451846
* ExprInParens ::= PostfixExpr `:' Type
18461847
* | Expr
18471848
* BlockResult ::= [‘implicit’] FunParams (‘=>’ | ‘?=>’) Block
1849+
* | HkTypeParamClause ‘=>’ Block
18481850
* | Expr1
18491851
* Expr1 ::= [‘inline’] `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
18501852
* | [‘inline’] `if' Expr `then' Expr [[semi] else Expr]
@@ -1855,7 +1857,6 @@ object Parsers {
18551857
* | `throw' Expr
18561858
* | `return' [Expr]
18571859
* | ForExpr
1858-
* | HkTypeParamClause ‘=>’ Expr
18591860
* | [SimpleExpr `.'] id `=' Expr
18601861
* | SimpleExpr1 ArgumentExprs `=' Expr
18611862
* | PostfixExpr [Ascription]
@@ -1876,28 +1877,41 @@ object Parsers {
18761877
def expr(location: Location): Tree = {
18771878
val start = in.offset
18781879
def isSpecialClosureStart = in.lookahead.isIdent(nme.erased) && in.erasedEnabled
1879-
if in.token == IMPLICIT then
1880-
closure(start, location, modifiers(BitSet(IMPLICIT)))
1881-
else if in.token == LPAREN && isSpecialClosureStart then
1882-
closure(start, location, Modifiers())
1883-
else {
1884-
val saved = placeholderParams
1885-
placeholderParams = Nil
1886-
1887-
def wrapPlaceholders(t: Tree) = try
1888-
if (placeholderParams.isEmpty) t
1889-
else new WildcardFunction(placeholderParams.reverse, t)
1890-
finally placeholderParams = saved
1891-
1892-
val t = expr1(location)
1893-
if in.isArrow then
1894-
placeholderParams = Nil // don't interpret `_' to the left of `=>` as placeholder
1895-
wrapPlaceholders(closureRest(start, location, convertToParams(t)))
1896-
else if isWildcard(t) then
1897-
placeholderParams = placeholderParams ::: saved
1898-
t
1899-
else wrapPlaceholders(t)
1900-
}
1880+
in.token match
1881+
case IMPLICIT =>
1882+
closure(start, location, modifiers(BitSet(IMPLICIT)))
1883+
case LPAREN if isSpecialClosureStart =>
1884+
closure(start, location, Modifiers())
1885+
case LBRACKET =>
1886+
val start = in.offset
1887+
val tparams = typeParamClause(ParamOwner.TypeParam)
1888+
val arrowOffset = accept(ARROW)
1889+
val body = expr(location)
1890+
atSpan(start, arrowOffset) {
1891+
if (isFunction(body))
1892+
PolyFunction(tparams, body)
1893+
else {
1894+
syntaxError("Implementation restriction: polymorphic function literals must have a value parameter", arrowOffset)
1895+
errorTermTree
1896+
}
1897+
}
1898+
case _ =>
1899+
val saved = placeholderParams
1900+
placeholderParams = Nil
1901+
1902+
def wrapPlaceholders(t: Tree) = try
1903+
if (placeholderParams.isEmpty) t
1904+
else new WildcardFunction(placeholderParams.reverse, t)
1905+
finally placeholderParams = saved
1906+
1907+
val t = expr1(location)
1908+
if in.isArrow then
1909+
placeholderParams = Nil // don't interpret `_' to the left of `=>` as placeholder
1910+
wrapPlaceholders(closureRest(start, location, convertToParams(t)))
1911+
else if isWildcard(t) then
1912+
placeholderParams = placeholderParams ::: saved
1913+
t
1914+
else wrapPlaceholders(t)
19011915
}
19021916

19031917
def expr1(location: Location = Location.ElseWhere): Tree = in.token match
@@ -1981,19 +1995,6 @@ object Parsers {
19811995
}
19821996
case FOR =>
19831997
forExpr()
1984-
case LBRACKET =>
1985-
val start = in.offset
1986-
val tparams = typeParamClause(ParamOwner.TypeParam)
1987-
val arrowOffset = accept(ARROW)
1988-
val body = expr()
1989-
atSpan(start, arrowOffset) {
1990-
if (isFunction(body))
1991-
PolyFunction(tparams, body)
1992-
else {
1993-
syntaxError("Implementation restriction: polymorphic function literals must have a value parameter", arrowOffset)
1994-
errorTermTree
1995-
}
1996-
}
19971998
case _ =>
19981999
if isIdent(nme.inline)
19992000
&& !in.inModifierPosition()

docs/docs/internals/syntax.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ Types ::= Type {‘,’ Type}
205205
### Expressions
206206
```ebnf
207207
Expr ::= FunParams (‘=>’ | ‘?=>’) Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
208+
| HkTypeParamClause ‘=>’ Expr PolyFunction(ts, expr)
208209
| Expr1
209210
BlockResult ::= FunParams (‘=>’ | ‘?=>’) Block
211+
| HkTypeParamClause ‘=>’ Block
210212
| Expr1
211213
FunParams ::= Bindings
212214
| id
@@ -220,7 +222,6 @@ Expr1 ::= [‘inline’] ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[
220222
| ‘throw’ Expr Throw(expr)
221223
| ‘return’ [Expr] Return(expr?)
222224
| ForExpr
223-
| HkTypeParamClause ‘=>’ Expr PolyFunction(ts, expr)
224225
| [SimpleExpr ‘.’] id ‘=’ Expr Assign(expr, expr)
225226
| SimpleExpr1 ArgumentExprs ‘=’ Expr Assign(expr, expr)
226227
| PostfixExpr [Ascription]

docs/docs/reference/syntax.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ Types ::= Type {‘,’ Type}
202202
### Expressions
203203
```ebnf
204204
Expr ::= FunParams (‘=>’ | ‘?=>’) Expr
205+
| HkTypeParamClause ‘=>’ Expr
205206
| Expr1
206207
BlockResult ::= FunParams (‘=>’ | ‘?=>’) Block
208+
| HkTypeParamClause ‘=>’ Block
207209
| Expr1
208210
FunParams ::= Bindings
209211
| id
@@ -217,7 +219,6 @@ Expr1 ::= [‘inline’] ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[
217219
| ‘throw’ Expr
218220
| ‘return’ [Expr]
219221
| ForExpr
220-
| HkTypeParamClause ‘=>’ Expr
221222
| [SimpleExpr ‘.’] id ‘=’ Expr
222223
| SimpleExpr1 ArgumentExprs ‘=’ Expr
223224
| PostfixExpr [Ascription]

tests/neg/tuple-ops.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ val r3: ((2, 1), (8, 2)) = c.zip(a) // error
1212
// Map
1313
case class Foo[X](x: X)
1414

15-
val r6: (Int, Int, String) = a.map[[t] =>> Int]([t] => x: t => x match { // error
15+
val r6: (Int, Int, String) = a.map[[t] =>> Int]([t] => (x: t) => x match { // error
1616
case x: Int => x * x
1717
case _ => ???
1818
})
1919

2020
val r7: ((1, Foo[1]), (2), (3, Foo[3])) =
21-
a.map[[t] =>> (t, Foo[t])]( [t] => x: t => (x, Foo(x)) ) // error
21+
a.map[[t] =>> (t, Foo[t])]( [t] => (x: t) => (x, Foo(x)) ) // error
2222

2323
// More Zip
2424
val t1: Int *: Long *: Tuple = (1, 2l, 100, 200)

tests/pos/i12277.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
def foo(f: => () => Unit): Unit = ???
2+
def boo(f: [A] => () => Unit): Unit = ???
3+
4+
object test:
5+
foo { () => // okay
6+
println(1)
7+
println(2)
8+
}
9+
10+
boo { [A] => () => // error
11+
println(1)
12+
println(2)
13+
}
14+
15+
boo { [A] => () => { // okay
16+
println(1)
17+
println(2)
18+
}}

0 commit comments

Comments
 (0)