Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 07611bf

Browse files
committed
Put extensions under language.experimental.relaxedLambdaSyntax
1 parent 8665a3c commit 07611bf

File tree

10 files changed

+41
-20
lines changed

10 files changed

+41
-20
lines changed

‎compiler/src/dotty/tools/dotc/config/Feature.scala‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ object Feature:
3838
val quotedPatternsWithPolymorphicFunctions = experimental("quotedPatternsWithPolymorphicFunctions")
3939
val packageObjectValues = experimental("packageObjectValues")
4040
val subCases = experimental("subCases")
41+
val relaxedLambdaSyntax = experimental("relaxedLambdaSyntax")
4142

4243
def experimentalAutoEnableFeatures(using Context): List[TermName] =
4344
defn.languageExperimentalFeatures

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

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,18 +1086,20 @@ object Parsers {
10861086

10871087
/** Is the token sequence following the current `:` token classified as a lambda?
10881088
* If yes return a defined parsing function to parse the lambda body, if not
1089-
* return None. The case is triggered in two :if the input starts with an identifier,
1090-
* a wildcard, or something enclosed in (...) or [...], this is followed by a
1091-
* `=>` or `?=>`, one one of the following two cases applies:
1092-
* 1. The next token is an indent. In this case the return parsing function parses
1093-
* an Expr in location Location.InColonArg.
1094-
* 2. The next token is on the same line and the enclosing region is not `(...)`.
1095-
* In this case the parsing function parses an Expr in location Location.InColonArg
1096-
* enclosed in a SingleLineLambda region, and then eats the ENDlambda token
1097-
* generated by the Scanner at the end of that region.
1098-
* The reason for excluding (2) in regions enclosed in parentheses is to avoid
1099-
* an ambiguity with type ascription `(x: A => B)`, where function types are only
1100-
* allowed inside parentheses.
1089+
* return None. The case is triggered in two situations:
1090+
* 1. If the input starts with an identifier, a wildcard, or something
1091+
* enclosed in (...) or [...], this is followed by a `=>` or `?=>`,
1092+
* and one of the following two subcases applies:
1093+
* 1a. The next token is an indent. In this case the return parsing function parses
1094+
* an Expr in location Location.InColonArg.
1095+
* 1b. Under relaxedLambdaSyntax: the next token is on the same line and the enclosing region is not `(...)`.
1096+
* In this case the parsing function parses an Expr in location Location.InColonArg
1097+
* enclosed in a SingleLineLambda region, and then eats the ENDlambda token
1098+
* generated by the Scanner at the end of that region.
1099+
* The reason for excluding (1b) in regions enclosed in parentheses is to avoid
1100+
* an ambiguity with type ascription `(x: A => B)`, where function types are only
1101+
* allowed inside parentheses.
1102+
* 2. Under relaxedLambdaSyntax: the input starts with a `case`.
11011103
*/
11021104
def followingIsLambdaAfterColon(): Option[() => Tree] =
11031105
val lookahead = in.LookaheadScanner(allowIndent = true)
@@ -1107,7 +1109,9 @@ object Parsers {
11071109
lookahead.observeArrowIndented()
11081110
if lookahead.token == INDENT || lookahead.token == EOF then
11091111
Some(() => expr(Location.InColonArg))
1110-
else if !in.currentRegion.isInstanceOf[InParens] then
1112+
else if in.featureEnabled(Feature.relaxedLambdaSyntax)
1113+
&& !in.currentRegion.isInstanceOf[InParens]
1114+
then
11111115
Some: () =>
11121116
val t = inSepRegion(SingleLineLambda(_)):
11131117
expr(Location.InColonArg)
@@ -1122,7 +1126,7 @@ object Parsers {
11221126
else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
11231127
lookahead.skipParens()
11241128
isArrowIndent()
1125-
else if lookahead.token == CASE then
1129+
else if lookahead.token == CASE && in.featureEnabled(Feature.relaxedLambdaSyntax) then
11261130
Some(() => singleCaseMatch())
11271131
else
11281132
None
@@ -1193,9 +1197,11 @@ object Parsers {
11931197
/** Optionally, if we are seeing a lambda argument after a colon of the form
11941198
* : (params) =>
11951199
* body
1196-
* or a single-line lambda
1200+
* or a single-line lambda (under relaxedLambdaSyntax)
11971201
* : (params) => body
1198-
* then return the function used to parse `body`.
1202+
* or a case clause (under relaxedLambdaSyntax)
1203+
* : case pat guard => rhs
1204+
* then return the function used to parse `body` or the case clause.
11991205
*/
12001206
def detectColonLambda: Option[() => Tree] =
12011207
if sourceVersion.enablesFewerBraces && in.token == COLONfollow
@@ -2432,7 +2438,7 @@ object Parsers {
24322438
val arrowOffset = accept(ARROW)
24332439
val body = expr(location)
24342440
makePolyFunction(tparams, body, "literal", errorTermTree(arrowOffset), start, arrowOffset)
2435-
case CASE =>
2441+
case CASE if in.featureEnabled(Feature.relaxedLambdaSyntax) =>
24362442
singleCaseMatch()
24372443
case _ =>
24382444
val saved = placeholderParams

‎library/src/scala/language.scala‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,10 @@ object language {
355355
@compileTimeOnly("`subCases` can only be used at compile time in import statements")
356356
object subCases
357357

358+
/** Experimental support for single-line lambdas and case clause expressions after `:`
359+
*/
360+
@compileTimeOnly("`relaxedLambdaSyntax` can only be used at compile time in import statements")
361+
object relaxedLambdaSyntax
358362
}
359363

360364
/** The deprecated object contains features that are no longer officially suypported in Scala.

‎library/src/scala/runtime/stdLibPatches/language.scala‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ object language:
161161
*/
162162
@compileTimeOnly("`subCases` can only be used at compile time in import statements")
163163
object subCases
164+
165+
/** Experimental support for single-line lambdas and case clause expressions after `:`
166+
*/
167+
@compileTimeOnly("`relaxedLambdaSyntax` can only be used at compile time in import statements")
168+
object relaxedLambdaSyntax
164169
end experimental
165170

166171
/** The deprecated object contains features that are no longer officially suypported in Scala.

‎tests/neg/closure-args.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
importlanguage.experimental.relaxedLambdaSyntax
22
val x = List(1).map: (x: => Int) => // error
33
???
44
val z = List(1).map: + => // ok

‎tests/neg/i22193.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
importlanguage.experimental.relaxedLambdaSyntax
22
def fn2(arg: String, arg2: String)(f: String => Unit): Unit = f(arg)
33

44
def fn3(arg: String, arg2: String)(f: => Unit): Unit = f

‎tests/neg/i22906.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//> using options -rewrite -indent
22
//> nominally using scala 3.7.0-RC1
33
// does not reproduce under "vulpix" test rig, which enforces certain flag sets?
4-
4+
importlanguage.experimental.relaxedLambdaSyntax
55
def program: Int => Int =
66
{`1`: Int => 5} // error // error

‎tests/pos/change-lambda.scala‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import language.experimental.relaxedLambdaSyntax
2+
13
def foo(x: Any) = ???
24

35
def test(xs: List[Int]) =

‎tests/pos/closure-args.scala‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import language.experimental.relaxedLambdaSyntax
12

23
val z = List(1).map: + => // ok
34
???

‎tests/run/single-case-expr.scala‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import language.experimental.relaxedLambdaSyntax
2+
13
case class Foo(x: Int, y: Int)
24
@main def Test =
35
val f: List[Int] => Int = case y :: ys => y

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /