Skip to content

Commit 8acfe27

Browse files
committed
Make better-fors a preview feature
1 parent cefa37b commit 8acfe27

File tree

12 files changed

+56
-17
lines changed

12 files changed

+56
-17
lines changed

Diff for: compiler/src/dotty/tools/dotc/ast/Desugar.scala

+10-10
Original file line numberDiff line numberDiff line change
@@ -1953,9 +1953,9 @@ object desugar {
19531953
/** Create tree for for-comprehension `<for (enums) do body>` or
19541954
* `<for (enums) yield body>` where mapName and flatMapName are chosen
19551955
* corresponding to whether this is a for-do or a for-yield.
1956-
* If sourceVersion >= 3.7 are enabled, the creation performs the following rewrite rules:
1956+
* If betterFors are enabled, the creation performs the following rewrite rules:
19571957
*
1958-
* 1. if sourceVersion >= 3.7:
1958+
* 1. if betterFors is enabled:
19591959
*
19601960
* for () do E ==> E
19611961
* or
@@ -1986,13 +1986,13 @@ object desugar {
19861986
* ==>
19871987
* for (P <- G.withFilter (P => E); ...) ...
19881988
*
1989-
* 6. For any N, if sourceVersion >= 3.7:
1989+
* 6. For any N, if betterFors is enabled:
19901990
*
19911991
* for (P <- G; P_1 = E_1; ... P_N = E_N; P1 <- G1; ...) ...
19921992
* ==>
19931993
* G.flatMap (P => for (P_1 = E_1; ... P_N = E_N; ...))
19941994
*
1995-
* 7. For any N, if sourceVersion >= 3.7:
1995+
* 7. For any N, if betterFors is enabled:
19961996
*
19971997
* for (P <- G; P_1 = E_1; ... P_N = E_N) ...
19981998
* ==>
@@ -2013,7 +2013,7 @@ object desugar {
20132013
* If any of the P_i are variable patterns, the corresponding `x_i @ P_i` is not generated
20142014
* and the variable constituting P_i is used instead of x_i
20152015
*
2016-
* 9. For any N, if sourceVersion >= 3.7:
2016+
* 9. For any N, if betterFors is enabled:
20172017
*
20182018
* for (P_1 = E_1; ... P_N = E_N; ...)
20192019
* ==>
@@ -2157,15 +2157,15 @@ object desugar {
21572157
case _ => false
21582158

21592159
def markTrailingMap(aply: Apply, gen: GenFrom, selectName: TermName): Unit =
2160-
if sourceVersion.isAtLeast(`3.7`)
2160+
if sourceVersion.enablesBetterFors
21612161
&& selectName == mapName
21622162
&& gen.checkMode != GenCheckMode.Filtered // results of withFilter have the wrong type
21632163
&& (deepEquals(gen.pat, body) || deepEquals(body, Tuple(Nil)))
21642164
then
21652165
aply.putAttachment(TrailingForMap, ())
21662166

21672167
enums match {
2168-
case Nil if sourceVersion.isAtLeast(`3.7`) => body
2168+
case Nil if sourceVersion.enablesBetterFors => body
21692169
case (gen: GenFrom) :: Nil =>
21702170
val aply = Apply(rhsSelect(gen, mapName), makeLambda(gen, body))
21712171
markTrailingMap(aply, gen, mapName)
@@ -2174,7 +2174,7 @@ object desugar {
21742174
val cont = makeFor(mapName, flatMapName, rest, body)
21752175
Apply(rhsSelect(gen, flatMapName), makeLambda(gen, cont))
21762176
case (gen: GenFrom) :: rest
2177-
if sourceVersion.isAtLeast(`3.7`)
2177+
if sourceVersion.enablesBetterFors
21782178
&& rest.dropWhile(_.isInstanceOf[GenAlias]).headOption.forall(e => e.isInstanceOf[GenFrom]) // possible aliases followed by a generator or end of for
21792179
&& !rest.takeWhile(_.isInstanceOf[GenAlias]).exists(a => isNestedGivenPattern(a.asInstanceOf[GenAlias].pat)) =>
21802180
val cont = makeFor(mapName, flatMapName, rest, body)
@@ -2202,9 +2202,9 @@ object desugar {
22022202
makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
22032203
case (gen: GenFrom) :: test :: rest =>
22042204
val filtered = Apply(rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2205-
val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.isAtLeast(`3.7`) then GenCheckMode.Filtered else GenCheckMode.Ignore)
2205+
val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.enablesBetterFors then GenCheckMode.Filtered else GenCheckMode.Ignore)
22062206
makeFor(mapName, flatMapName, genFrom :: rest, body)
2207-
case GenAlias(_, _) :: _ if sourceVersion.isAtLeast(`3.7`) =>
2207+
case GenAlias(_, _) :: _ if sourceVersion.enablesBetterFors =>
22082208
val (valeqs, rest) = enums.span(_.isInstanceOf[GenAlias])
22092209
val pats = valeqs.map { case GenAlias(pat, _) => pat }
22102210
val rhss = valeqs.map { case GenAlias(_, rhs) => rhs }

Diff for: compiler/src/dotty/tools/dotc/config/SourceVersion.scala

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package dotc
33
package config
44

55
import core.Decorators.*
6+
import core.Contexts.*
7+
import Feature.isPreviewEnabled
68
import util.Property
79

810
enum SourceVersion:
@@ -35,6 +37,7 @@ enum SourceVersion:
3537
def enablesClauseInterleaving = isAtLeast(`3.6`)
3638
def enablesNewGivens = isAtLeast(`3.6`)
3739
def enablesNamedTuples = isAtLeast(`3.7`)
40+
def enablesBetterFors(using Context) = isAtLeast(`3.7`) && isPreviewEnabled
3841

3942
object SourceVersion extends Property.Key[SourceVersion]:
4043
def defaultSourceVersion = `3.7`

Diff for: compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,7 @@ object Parsers {
29562956
/** Enumerators ::= Generator {semi Enumerator | Guard}
29572957
*/
29582958
def enumerators(): List[Tree] =
2959-
if sourceVersion.isAtLeast(`3.7`) then
2959+
if sourceVersion.enablesBetterFors then
29602960
aliasesUntilGenerator() ++ enumeratorsRest()
29612961
else
29622962
generator() :: enumeratorsRest()

Diff for: docs/_docs/reference/changed-features/better-fors.md renamed to docs/_docs/reference/preview/better-fors.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
layout: doc-page
33
title: "Better fors"
4-
nightlyOf: https://docs.scala-lang.org/scala3/reference/changed-features/better-fors.html
4+
nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/better-fors.html
55
---
66

7-
Starting in Scala `3.7`, the usability of `for`-comprehensions is improved.
7+
Starting in Scala `3.7` under `-preview` mode, the usability of `for`-comprehensions is improved.
88

99
The biggest user facing change is the new ability to start `for`-comprehensions with aliases. This means that the following previously invalid code is now valid:
1010

Diff for: docs/_docs/reference/preview/overview.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
layout: doc-page
3+
title: "Preview"
4+
nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/overview.html
5+
---
6+
7+
## Preview language features
8+
9+
New Scala language features or standard library APIs are initially introduced as experimental, but once they become fully implemented and accepted by the [SIP](https://docs.scala-lang.org/sips/) these can become a preview features.
10+
11+
Preview language features and APIs are guaranteed to be standardized in some next Scala minor release, but allow the compiler team to introduce small, possibly binary incompatible, changes based on the community feedback.
12+
These can be used by early adopters who can accept the possibility of binary compatibility breakage. For instance, preview features could be used in some internal tool or application. On the other hand, preview features are discouraged in publicly available libraries.
13+
14+
More information about preview featues can be found in [preview defintions guide](../other-new-features/preview-defs.md)
15+
16+
### `-preview` compiler flag
17+
18+
This flag enables the use of all preview language feature in the project.
19+
20+
21+
## List of available preview features
22+
23+
* [`better-fors`](./better-fors.md): Enables new for-comprehension behaviour under SIP-62 under `-source:3.7` or later
24+

Diff for: docs/sidebar.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ subsection:
116116
- page: reference/changed-features/lazy-vals-init.md
117117
- page: reference/changed-features/main-functions.md
118118
- page: reference/changed-features/interpolation-escapes.md
119-
- page: reference/changed-features/better-fors.md
120119
- title: Dropped Features
121120
index: reference/dropped-features/dropped-features.md
122121
subsection:
@@ -140,6 +139,11 @@ subsection:
140139
- page: reference/dropped-features/nonlocal-returns.md
141140
- page: reference/dropped-features/this-qualifier.md
142141
- page: reference/dropped-features/wildcard-init.md
142+
- title: Preview Features
143+
directory: preview
144+
index: reference/preview/overview.md
145+
subsection:
146+
- page: reference/preview/better-fors.md
143147
- title: Experimental Features
144148
directory: experimental
145149
index: reference/experimental/overview.md

Diff for: library/src/scala/runtime/stdLibPatches/language.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ object language:
140140
* @see [[https://github.com/scala/improvement-proposals/pull/79]]
141141
*/
142142
@compileTimeOnly("`betterFors` can only be used at compile time in import statements")
143-
@deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now standard", since = "3.7")
143+
@deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now in preview", since = "3.7")
144144
object betterFors
145145

146146
/** Experimental support for package object values

Diff for: tests/pos/better-fors-given.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//> using options -preview
2+
13
@main def Test: Unit =
24
for
35
x <- Option(23 -> "abc")

Diff for: tests/pos/better-fors-i21804.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import scala.language.experimental.betterFors
1+
//> using options -preview
2+
// import scala.language.experimental.betterFors
23

34
case class Container[A](val value: A) {
45
def map[B](f: A => B): Container[B] = Container(f(value))

Diff for: tests/run/better-fors-map-elim.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import scala.language.experimental.betterFors
1+
//> using options -preview
2+
// import scala.language.experimental.betterFors
23

34
class myOptionModule(doOnMap: => Unit) {
45
sealed trait MyOption[+A] {

Diff for: tests/run/better-fors.scala

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//> using options -preview
2+
// import scala.language.experimental.betterFors
3+
14
def for1 =
25
for {
36
a = 1

Diff for: tests/run/fors.scala

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//> using options -preview
12
//############################################################################
23
// for-comprehensions (old and new syntax)
34
//############################################################################

0 commit comments

Comments
 (0)