Skip to content

Commit bd7c661

Browse files
committed
Implement parsing for multiple parameter lambdas with erased parameters
Contextual lambdas with erased parameters are also automatically supported.
1 parent e46c75f commit bd7c661

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

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

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,12 +2095,9 @@ object Parsers {
20952095

20962096
def expr(location: Location): Tree = {
20972097
val start = in.offset
2098-
def isSpecialClosureStart = in.lookahead.isIdent(nme.erased) && in.erasedEnabled
20992098
in.token match
21002099
case IMPLICIT =>
21012100
closure(start, location, modifiers(BitSet(IMPLICIT)))
2102-
case LPAREN if isSpecialClosureStart =>
2103-
closure(start, location, Modifiers())
21042101
case LBRACKET =>
21052102
val start = in.offset
21062103
val tparams = typeParamClause(ParamOwner.TypeParam)
@@ -2323,10 +2320,7 @@ object Parsers {
23232320
Nil
23242321
else
23252322
try
2326-
commaSeparated(() =>
2327-
val mods1 = if isErased then addModifier(mods) else mods
2328-
binding(mods1)
2329-
)
2323+
commaSeparated(() => binding(mods))
23302324
finally
23312325
accept(RPAREN)
23322326
else {
@@ -2350,10 +2344,13 @@ object Parsers {
23502344
(atSpan(start) { makeParameter(name, t, mods) }) :: Nil
23512345
}
23522346

2353-
/** Binding ::= (id | `_') [`:' Type]
2347+
/** Binding ::= [`erased`] (id | `_') [`:' Type]
23542348
*/
23552349
def binding(mods: Modifiers): Tree =
2356-
atSpan(in.offset) { makeParameter(bindingName(), typedOpt(), mods) }
2350+
atSpan(in.offset) {
2351+
val mods1 = if isErased then addModifier(mods) else mods
2352+
makeParameter(bindingName(), typedOpt(), mods1)
2353+
}
23572354

23582355
def bindingName(): TermName =
23592356
if (in.token == USCORE) {
@@ -2550,6 +2547,7 @@ object Parsers {
25502547
else in.currentRegion.withCommasExpected {
25512548
var isFormalParams = false
25522549
def exprOrBinding() =
2550+
if isErased then isFormalParams = true
25532551
if isFormalParams then binding(Modifiers())
25542552
else
25552553
val t = exprInParens()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
type F = (Int, erased Int) => Int
2+
3+
erased class A
4+
5+
@main def Test() =
6+
val a: F = (x, y) => x + 1 // error: Expected F got (Int, Int) => Int
7+
val b: F = (x, erased y) => x + 1 // ok
8+
val c: F = (_, _) => 5 // error: Expected F got (Int, Int) => Int
9+
val d: F = (_, erased _) => 5 // ok
10+
11+
def use(f: F) = f(5, 6)
12+
13+
use { (x, y) => x } // error: Expected F got (Int, Int) => Int
14+
15+
def singleParam(f: (erased Int) => Int) = f(5)
16+
17+
singleParam(x => 5) // error: Expected (erased Int) => Int got Int => Int
18+
singleParam((erased x) => 5) // ok
19+
20+
def erasedClass(f: A => Int) = f(new A)
21+
22+
erasedClass(_ => 5) // ok since A is implicitly erased
23+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// lambdas should parse and work
2+
3+
type F = (Int, erased String) => Int
4+
5+
def use(f: F) = f(5, "a")
6+
7+
val fv: F = (x, erased y) => x
8+
val fvExpl = (x: Int, erased y: String) => x
9+
10+
// contextual lambdas should work
11+
12+
type FC = (Int, erased String) ?=> Int
13+
14+
def useCtx(f: FC) = f(using 5, "a")
15+
16+
val fCv: FC = (x, erased y) ?=> x
17+
val fCvExpl = (x: Int, erased y: String) ?=> x
18+
19+
// nested lambdas should work
20+
21+
val nested: Int => (String, erased Int) => FC = a => (_, erased _) => (c, erased d) ?=> a + c
22+
23+
@main def Test() =
24+
assert(5 == use(fv))
25+
assert(5 == use(fvExpl))
26+
assert(5 == use { (x, erased y) => x })
27+
28+
assert(5 == useCtx(fCv))
29+
assert(5 == useCtx(fCvExpl))
30+
assert(5 == useCtx { (x, erased y) ?=> x })
31+
32+
assert(6 == useCtx(nested(1)("b", 2)))

0 commit comments

Comments
 (0)