Skip to content

Commit 783f5e7

Browse files
committed
Switch back to ?=> for context function closures
The old syntax was awkward since everywhere else after a `using` it's the _name of the paramater_ that's optional, not the type.
1 parent 6a56706 commit 783f5e7

File tree

12 files changed

+63
-63
lines changed

12 files changed

+63
-63
lines changed

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -443,35 +443,35 @@ object Parsers {
443443

444444
/** Convert tree to formal parameter list
445445
*/
446-
def convertToParams(tree: Tree): List[ValDef] = tree match {
446+
def convertToParams(tree: Tree, mods: Modifiers): List[ValDef] = tree match {
447447
case Parens(t) =>
448-
convertToParam(t) :: Nil
448+
convertToParam(t, mods) :: Nil
449449
case Tuple(ts) =>
450-
ts.map(convertToParam(_))
450+
ts.map(convertToParam(_, mods))
451451
case t: Typed =>
452452
report.errorOrMigrationWarning(
453453
em"parentheses are required around the parameter of a lambda${rewriteNotice()}",
454454
in.sourcePos())
455455
if migrateTo3 then
456456
patch(source, t.span.startPos, "(")
457457
patch(source, t.span.endPos, ")")
458-
convertToParam(t) :: Nil
458+
convertToParam(t, mods) :: Nil
459459
case t =>
460-
convertToParam(t) :: Nil
460+
convertToParam(t, mods) :: Nil
461461
}
462462

463463
/** Convert tree to formal parameter
464464
*/
465-
def convertToParam(tree: Tree, expected: String = "formal parameter"): ValDef = tree match {
465+
def convertToParam(tree: Tree, mods: Modifiers, expected: String = "formal parameter"): ValDef = tree match {
466466
case id @ Ident(name) =>
467-
makeParameter(name.asTermName, TypeTree(), EmptyModifiers, isBackquoted = isBackquoted(id)).withSpan(tree.span)
467+
makeParameter(name.asTermName, TypeTree(), mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
468468
case Typed(id @ Ident(name), tpt) =>
469-
makeParameter(name.asTermName, tpt, EmptyModifiers, isBackquoted = isBackquoted(id)).withSpan(tree.span)
469+
makeParameter(name.asTermName, tpt, mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
470470
case Typed(Splice(Ident(name)), tpt) =>
471-
makeParameter(("$" + name).toTermName, tpt, EmptyModifiers).withSpan(tree.span)
471+
makeParameter(("$" + name).toTermName, tpt, mods).withSpan(tree.span)
472472
case _ =>
473473
syntaxError(s"not a legal $expected", tree.span)
474-
makeParameter(nme.ERROR, tree, EmptyModifiers)
474+
makeParameter(nme.ERROR, tree, mods)
475475
}
476476

477477
/** Convert (qual)ident to type identifier
@@ -1920,9 +1920,10 @@ object Parsers {
19201920
finally placeholderParams = saved
19211921

19221922
val t = expr1(location)
1923-
if (in.token == ARROW) {
1923+
if (in.token == ARROW || in.token == CTXARROW) {
19241924
placeholderParams = Nil // don't interpret `_' to the left of `=>` as placeholder
1925-
wrapPlaceholders(closureRest(start, location, convertToParams(t)))
1925+
val paramMods = if in.token == CTXARROW then Modifiers(Given) else EmptyModifiers
1926+
wrapPlaceholders(closureRest(start, location, convertToParams(t, paramMods)))
19261927
}
19271928
else if (isWildcard(t)) {
19281929
placeholderParams = placeholderParams ::: saved
@@ -2124,7 +2125,7 @@ object Parsers {
21242125
/** FunParams ::= Bindings
21252126
* | id
21262127
* | `_'
2127-
* Bindings ::= `(' [[‘using’] [‘erased’] Binding {`,' Binding}] `)'
2128+
* Bindings ::= `(' [[‘erased’] Binding {`,' Binding}] `)'
21282129
*/
21292130
def funParams(mods: Modifiers, location: Location): List[Tree] =
21302131
if in.token == LPAREN then

docs/docs/reference/contextual/context-functions-spec.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ trait ContextFunctionN[-T1 , ... , -TN, +R] {
2828
Context function types erase to normal function types, so these classes are
2929
generated on the fly for typechecking, but not realized in actual code.
3030

31-
Context function literals `(using x1: T1, ..., xn: Tn) => e` map
31+
Context function literals `(x1: T1, ..., xn: Tn) ?=> e` map
3232
context parameters `xi` of types `Ti` to the result of evaluating the expression `e`.
3333
The scope of each context parameter `xi` is `e`. The parameters must have pairwise distinct names.
3434

@@ -54,7 +54,7 @@ Note: The closing paragraph of the
5454
[Anonymous Functions section](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-functions)
5555
of Scala 2.12 is subsumed by context function types and should be removed.
5656

57-
Context function literals `(using x1: T1, ..., xn: Tn) => e` are
57+
Context function literals `(x1: T1, ..., xn: Tn) ?=> e` are
5858
automatically created for any expression `e` whose expected type is
5959
`scala.ContextFunctionN[T1, ..., Tn, R]`, unless `e` is
6060
itself a context function literal. This is analogous to the automatic

docs/docs/reference/contextual/context-functions.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Conversely, if the expected type of an expression `E` is a context function type
2727
`(T_1, ..., T_n) ?=> U` and `E` is not already an
2828
context function literal, `E` is converted to a context function literal by rewriting it to
2929
```scala
30-
(using x_1: T1, ..., x_n: Tn) => E
30+
(x_1: T1, ..., x_n: Tn) ?=> E
3131
```
3232
where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed
3333
before the expression `E` is typechecked, which means that `x_1`, ..., `x_n`
@@ -39,12 +39,12 @@ For example, continuing with the previous definitions,
3939
```scala
4040
def g(arg: Executable[Int]) = ...
4141

42-
g(22) // is expanded to g((using ev: ExecutionContext) => 22)
42+
g(22) // is expanded to g((ev: ExecutionContext) ?=> 22)
4343

44-
g(f(2)) // is expanded to g((using ev: ExecutionContext) => f(2)(using ev))
44+
g(f(2)) // is expanded to g((ev: ExecutionContext) ?=> f(2)(using ev))
4545

46-
g(ExecutionContext ?=> f(3)) // is expanded to g((using ev: ExecutionContext) => f(3)(using ev))
47-
g((using ctx: ExecutionContext) => f(22)(using ctx)) // is left as it is
46+
g((ctx: ExecutionContext) ?=> f(3)) // is expanded to g((ctx: ExecutionContext) ?=> f(3)(using ctx))
47+
g((ctx: ExecutionContext) ?=> f(3)(using ctx)) // is left as it is
4848
```
4949

5050
### Example: Builder Pattern
@@ -102,14 +102,14 @@ that would otherwise be necessary.
102102
```
103103
With that setup, the table construction code above compiles and expands to:
104104
```scala
105-
table { (using $t: Table) =>
105+
table { ($t: Table) ?=>
106106

107-
row { (using $r: Row) =>
107+
row { ($r: Row) ?=>
108108
cell("top left")(using $r)
109109
cell("top right")(using $r)
110110
}(using $t)
111111

112-
row { (using $r: Row) =>
112+
row { ($r: Row) ?=>
113113
cell("bottom left")(using $r)
114114
cell("bottom right")(using $r)
115115
}(using $t)

staging/src/scala/quoted/staging/staging.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package object staging:
77
*
88
* Usage:
99
* ```
10-
* val e: T = run { // (using Quotes) =>
10+
* val e: T = run { // (quotes: Quotes) ?=>
1111
* expr
1212
* }
1313
* ```
@@ -23,7 +23,7 @@ package object staging:
2323
*
2424
* Usage:
2525
* ```
26-
* val e: T = withQuotes { // (using Quotes) =>
26+
* val e: T = withQuotes { // (quotes: Quotes) ?=>
2727
* thunk
2828
* }
2929
* ```

tests/disabled/run/tupled-function-extension-method.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ object Test {
1717
println(f3(1, 2, 3))
1818
println(f25(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25))
1919

20-
val if1 = new Expr((using i: Int) => Tuple1(i))
21-
val if2 = new Expr((using i: Int, j: Int) => (i, i + j))
22-
val if3 = new Expr((using i: Int, j: Int, k: Int) => (i, i + j, i + j + k))
20+
val if1 = new Expr((i: Int) ?=> Tuple1(i))
21+
val if2 = new Expr((i: Int, j: Int) ?=> (i, i + j))
22+
val if3 = new Expr((i: Int, j: Int, k: Int) ?=> (i, i + j, i + j + k))
2323
val if25 = new Expr(
24-
(using x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int) =>
24+
(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int) ?=>
2525
(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25)
2626
)
2727

tests/neg/i2514a.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
object Foo {
22
def foo(): Int = {
3-
val f: Int ?=> Int = (using x: Int) => 2 * x
3+
val f: Int ?=> Int = (x: Int) ?=> 2 * x
44
f(using 2)
55
}
66

77
val f = implicit (x: Int) => x
88

9-
((using x: Int) => x): (Int ?=> Int) // error: no implicit argument found
9+
((x: Int) ?=> x): (Int ?=> Int) // error: no implicit argument found
1010
}
11-

tests/pos/i6862/lib_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
trait Ctx
2-
inline def foo(): Unit = (using x: Ctx) => ()
2+
inline def foo(): Unit = (x: Ctx) ?=> ()
33
def bar[T](b: Ctx ?=> Unit): Unit = ???

tests/run-custom-args/lambda-serialization-others.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ class C1 {
3636

3737
class C2
3838
extends Serializable /* Needed because of #5866 */ {
39-
val impfun: Int ?=> Int = (using x1) => x1
39+
val impfun: Int ?=> Int = x1 ?=> x1
4040

41-
val impdepfun: (x1: Int) ?=> List[x1.type] = (using x1) => List(x1)
41+
val impdepfun: (x1: Int) ?=> List[x1.type] = x1 ?=> List(x1)
4242

43-
val erasedimpfun: (erased Int) ?=> Int = (using erased x1) => 0
43+
val erasedimpfun: (erased Int) ?=> Int = (erased x1) ?=> 0
4444
}
4545

4646
object Test {

0 commit comments

Comments
 (0)