From 8acfe2717f0cf9eb6ef7d5165cd5212e745eb4eb Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 11 Mar 2025 18:40:15 +0100 Subject: [PATCH 1/5] Make better-fors a preview feature --- .../src/dotty/tools/dotc/ast/Desugar.scala | 20 ++++++++-------- .../tools/dotc/config/SourceVersion.scala | 3 +++ .../dotty/tools/dotc/parsing/Parsers.scala | 2 +- .../better-fors.md | 4 ++-- docs/_docs/reference/preview/overview.md | 24 +++++++++++++++++++ docs/sidebar.yml | 6 ++++- .../runtime/stdLibPatches/language.scala | 2 +- tests/pos/better-fors-given.scala | 2 ++ tests/pos/better-fors-i21804.scala | 3 ++- tests/run/better-fors-map-elim.scala | 3 ++- tests/run/better-fors.scala | 3 +++ tests/run/fors.scala | 1 + 12 files changed, 56 insertions(+), 17 deletions(-) rename docs/_docs/reference/{changed-features => preview}/better-fors.md (93%) create mode 100644 docs/_docs/reference/preview/overview.md diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1c86ba069433..c235143e97f1 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1953,9 +1953,9 @@ object desugar { /** Create tree for for-comprehension `` or * `` where mapName and flatMapName are chosen * corresponding to whether this is a for-do or a for-yield. - * If sourceVersion >= 3.7 are enabled, the creation performs the following rewrite rules: + * If betterFors are enabled, the creation performs the following rewrite rules: * - * 1. if sourceVersion >= 3.7: + * 1. if betterFors is enabled: * * for () do E ==> E * or @@ -1986,13 +1986,13 @@ object desugar { * ==> * for (P <- G.withFilter (P => E); ...) ... * - * 6. For any N, if sourceVersion >= 3.7: + * 6. For any N, if betterFors is enabled: * * for (P <- G; P_1 = E_1; ... P_N = E_N; P1 <- G1; ...) ... * ==> * G.flatMap (P => for (P_1 = E_1; ... P_N = E_N; ...)) * - * 7. For any N, if sourceVersion >= 3.7: + * 7. For any N, if betterFors is enabled: * * for (P <- G; P_1 = E_1; ... P_N = E_N) ... * ==> @@ -2013,7 +2013,7 @@ object desugar { * If any of the P_i are variable patterns, the corresponding `x_i @ P_i` is not generated * and the variable constituting P_i is used instead of x_i * - * 9. For any N, if sourceVersion >= 3.7: + * 9. For any N, if betterFors is enabled: * * for (P_1 = E_1; ... P_N = E_N; ...) * ==> @@ -2157,7 +2157,7 @@ object desugar { case _ => false def markTrailingMap(aply: Apply, gen: GenFrom, selectName: TermName): Unit = - if sourceVersion.isAtLeast(`3.7`) + if sourceVersion.enablesBetterFors && selectName == mapName && gen.checkMode != GenCheckMode.Filtered // results of withFilter have the wrong type && (deepEquals(gen.pat, body) || deepEquals(body, Tuple(Nil))) @@ -2165,7 +2165,7 @@ object desugar { aply.putAttachment(TrailingForMap, ()) enums match { - case Nil if sourceVersion.isAtLeast(`3.7`) => body + case Nil if sourceVersion.enablesBetterFors => body case (gen: GenFrom) :: Nil => val aply = Apply(rhsSelect(gen, mapName), makeLambda(gen, body)) markTrailingMap(aply, gen, mapName) @@ -2174,7 +2174,7 @@ object desugar { val cont = makeFor(mapName, flatMapName, rest, body) Apply(rhsSelect(gen, flatMapName), makeLambda(gen, cont)) case (gen: GenFrom) :: rest - if sourceVersion.isAtLeast(`3.7`) + if sourceVersion.enablesBetterFors && rest.dropWhile(_.isInstanceOf[GenAlias]).headOption.forall(e => e.isInstanceOf[GenFrom]) // possible aliases followed by a generator or end of for && !rest.takeWhile(_.isInstanceOf[GenAlias]).exists(a => isNestedGivenPattern(a.asInstanceOf[GenAlias].pat)) => val cont = makeFor(mapName, flatMapName, rest, body) @@ -2202,9 +2202,9 @@ object desugar { makeFor(mapName, flatMapName, vfrom1 :: rest1, body) case (gen: GenFrom) :: test :: rest => val filtered = Apply(rhsSelect(gen, nme.withFilter), makeLambda(gen, test)) - val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.isAtLeast(`3.7`) then GenCheckMode.Filtered else GenCheckMode.Ignore) + val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.enablesBetterFors then GenCheckMode.Filtered else GenCheckMode.Ignore) makeFor(mapName, flatMapName, genFrom :: rest, body) - case GenAlias(_, _) :: _ if sourceVersion.isAtLeast(`3.7`) => + case GenAlias(_, _) :: _ if sourceVersion.enablesBetterFors => val (valeqs, rest) = enums.span(_.isInstanceOf[GenAlias]) val pats = valeqs.map { case GenAlias(pat, _) => pat } val rhss = valeqs.map { case GenAlias(_, rhs) => rhs } diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index 199350949233..30a88fb79f2a 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -3,6 +3,8 @@ package dotc package config import core.Decorators.* +import core.Contexts.* +import Feature.isPreviewEnabled import util.Property enum SourceVersion: @@ -35,6 +37,7 @@ enum SourceVersion: def enablesClauseInterleaving = isAtLeast(`3.6`) def enablesNewGivens = isAtLeast(`3.6`) def enablesNamedTuples = isAtLeast(`3.7`) + def enablesBetterFors(using Context) = isAtLeast(`3.7`) && isPreviewEnabled object SourceVersion extends Property.Key[SourceVersion]: def defaultSourceVersion = `3.7` diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index f87f0d957325..20eb6e9b33fa 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2956,7 +2956,7 @@ object Parsers { /** Enumerators ::= Generator {semi Enumerator | Guard} */ def enumerators(): List[Tree] = - if sourceVersion.isAtLeast(`3.7`) then + if sourceVersion.enablesBetterFors then aliasesUntilGenerator() ++ enumeratorsRest() else generator() :: enumeratorsRest() diff --git a/docs/_docs/reference/changed-features/better-fors.md b/docs/_docs/reference/preview/better-fors.md similarity index 93% rename from docs/_docs/reference/changed-features/better-fors.md rename to docs/_docs/reference/preview/better-fors.md index 36355f0faa88..d5fd32da9a1e 100644 --- a/docs/_docs/reference/changed-features/better-fors.md +++ b/docs/_docs/reference/preview/better-fors.md @@ -1,10 +1,10 @@ --- layout: doc-page title: "Better fors" -nightlyOf: https://docs.scala-lang.org/scala3/reference/changed-features/better-fors.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/better-fors.html --- -Starting in Scala `3.7`, the usability of `for`-comprehensions is improved. +Starting in Scala `3.7` under `-preview` mode, the usability of `for`-comprehensions is improved. 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: diff --git a/docs/_docs/reference/preview/overview.md b/docs/_docs/reference/preview/overview.md new file mode 100644 index 000000000000..ec8d36bdfd25 --- /dev/null +++ b/docs/_docs/reference/preview/overview.md @@ -0,0 +1,24 @@ +--- +layout: doc-page +title: "Preview" +nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/overview.html +--- + +## Preview language features + +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. + +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. +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. + +More information about preview featues can be found in [preview defintions guide](../other-new-features/preview-defs.md) + +### `-preview` compiler flag + +This flag enables the use of all preview language feature in the project. + + +## List of available preview features + +* [`better-fors`](./better-fors.md): Enables new for-comprehension behaviour under SIP-62 under `-source:3.7` or later + diff --git a/docs/sidebar.yml b/docs/sidebar.yml index ca58e21587eb..aecd974326ab 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -116,7 +116,6 @@ subsection: - page: reference/changed-features/lazy-vals-init.md - page: reference/changed-features/main-functions.md - page: reference/changed-features/interpolation-escapes.md - - page: reference/changed-features/better-fors.md - title: Dropped Features index: reference/dropped-features/dropped-features.md subsection: @@ -140,6 +139,11 @@ subsection: - page: reference/dropped-features/nonlocal-returns.md - page: reference/dropped-features/this-qualifier.md - page: reference/dropped-features/wildcard-init.md + - title: Preview Features + directory: preview + index: reference/preview/overview.md + subsection: + - page: reference/preview/better-fors.md - title: Experimental Features directory: experimental index: reference/experimental/overview.md diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index 556df0e2759a..0e6b59731047 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -140,7 +140,7 @@ object language: * @see [[https://github.com/scala/improvement-proposals/pull/79]] */ @compileTimeOnly("`betterFors` can only be used at compile time in import statements") - @deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now standard", since = "3.7") + @deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now in preview", since = "3.7") object betterFors /** Experimental support for package object values diff --git a/tests/pos/better-fors-given.scala b/tests/pos/better-fors-given.scala index e4d64bbb30f3..6f70c5549469 100644 --- a/tests/pos/better-fors-given.scala +++ b/tests/pos/better-fors-given.scala @@ -1,3 +1,5 @@ +//> using options -preview + @main def Test: Unit = for x <- Option(23 -> "abc") diff --git a/tests/pos/better-fors-i21804.scala b/tests/pos/better-fors-i21804.scala index 7c8c753bf7c3..85ffb87b0296 100644 --- a/tests/pos/better-fors-i21804.scala +++ b/tests/pos/better-fors-i21804.scala @@ -1,4 +1,5 @@ -import scala.language.experimental.betterFors +//> using options -preview +// import scala.language.experimental.betterFors case class Container[A](val value: A) { def map[B](f: A => B): Container[B] = Container(f(value)) diff --git a/tests/run/better-fors-map-elim.scala b/tests/run/better-fors-map-elim.scala index 653984bc8e28..6f4db6573dec 100644 --- a/tests/run/better-fors-map-elim.scala +++ b/tests/run/better-fors-map-elim.scala @@ -1,4 +1,5 @@ -import scala.language.experimental.betterFors +//> using options -preview +// import scala.language.experimental.betterFors class myOptionModule(doOnMap: => Unit) { sealed trait MyOption[+A] { diff --git a/tests/run/better-fors.scala b/tests/run/better-fors.scala index 6b7e74ad9b4f..b0912aacd4dc 100644 --- a/tests/run/better-fors.scala +++ b/tests/run/better-fors.scala @@ -1,3 +1,6 @@ +//> using options -preview +// import scala.language.experimental.betterFors + def for1 = for { a = 1 diff --git a/tests/run/fors.scala b/tests/run/fors.scala index f08b8790cf34..4e802af4c53d 100644 --- a/tests/run/fors.scala +++ b/tests/run/fors.scala @@ -1,3 +1,4 @@ +//> using options -preview //############################################################################ // for-comprehensions (old and new syntax) //############################################################################ From 1812599f7f6ba734db5a349d2c47424a36764876 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 11 Mar 2025 20:00:37 +0100 Subject: [PATCH 2/5] Enable -preview in SemanticTokensSuite --- .../dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala index ca0b98de46f8..200f74537591 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala @@ -1,10 +1,14 @@ package dotty.tools.pc.tests.tokens import dotty.tools.pc.base.BaseSemanticTokensSuite +import java.nio.file.Path import org.junit.Test class SemanticTokensSuite extends BaseSemanticTokensSuite: + // -preview required for `for-comprehension` test + override protected def scalacOptions(classpath: Seq[Path]): Seq[String] = + super.scalacOptions(classpath) ++ Seq("-preview") @Test def `class, object, var, val(readonly), method, type, parameter, String(single-line)` = check( From bd328a6e97525cc06ae0181b8a9a161e07e82278 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 11 Mar 2025 20:04:27 +0100 Subject: [PATCH 3/5] Add more verbose deprecation message for `language.experimental.betterFors` --- library/src/scala/runtime/stdLibPatches/language.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index 0e6b59731047..8899f734aece 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -140,7 +140,7 @@ object language: * @see [[https://github.com/scala/improvement-proposals/pull/79]] */ @compileTimeOnly("`betterFors` can only be used at compile time in import statements") - @deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now in preview", since = "3.7") + @deprecated("The `experimental.betterFors` language import no longer has any effect, the feature is being stablised and can be enabled using `-preview` flag", since = "3.7") object betterFors /** Experimental support for package object values From bde44846a53530bc018389eed9ede849295d4d04 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 11 Mar 2025 22:34:46 +0100 Subject: [PATCH 4/5] Handle failing ExpressionCompoler tests - duplicate eval-in-for-comprehension test for preview and non-preview mode --- .../test/dotty/tools/debug/DebugTests.scala | 3 ++- .../eval-in-for-comprehension.check | 27 +++++++++++++++++++ .../eval-in-for-comprehension.scala | 14 ++++++++++ tests/debug/eval-in-for-comprehension.check | 7 +++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/debug-preview/eval-in-for-comprehension.check create mode 100644 tests/debug-preview/eval-in-for-comprehension.scala diff --git a/compiler/test/dotty/tools/debug/DebugTests.scala b/compiler/test/dotty/tools/debug/DebugTests.scala index 95bf5a2e52a6..e8f744286ba4 100644 --- a/compiler/test/dotty/tools/debug/DebugTests.scala +++ b/compiler/test/dotty/tools/debug/DebugTests.scala @@ -18,7 +18,8 @@ class DebugTests: implicit val testGroup: TestGroup = TestGroup("debug") CompilationTest.aggregateTests( compileFile("tests/debug-custom-args/eval-explicit-nulls.scala", TestConfiguration.explicitNullsOptions), - compileFilesInDir("tests/debug", TestConfiguration.defaultOptions) + compileFilesInDir("tests/debug", TestConfiguration.defaultOptions), + compileFilesInDir("tests/debug-preview", TestConfiguration.defaultOptions.and("-preview")) ).checkDebug() object DebugTests extends ParallelTesting: diff --git a/tests/debug-preview/eval-in-for-comprehension.check b/tests/debug-preview/eval-in-for-comprehension.check new file mode 100644 index 000000000000..6e91c891ebdb --- /dev/null +++ b/tests/debug-preview/eval-in-for-comprehension.check @@ -0,0 +1,27 @@ +break Test$ 5 // in main +eval list(0) +result 1 +// TODO can we remove debug line in adapted methods? +break Test$ 5 // in main$$anonfun$adapted$1 +break Test$ 6 // in main$$anonfun$1 +eval list(0) +result 1 +eval x +result 1 +break Test$ 7 // in main$$anonfun$1$$anonfun$1 +eval x + y +result 2 + +break Test$ 11 // in main$$anonfun$2 +eval x +result 1 + +break Test$ 13 // in main +eval list(0) +result 1 +break Test$ 13 // in main$$anonfun$4 + +break Test$ 14 // in main +eval list(0) +result 1 +break Test$ 14 // in main$$anonfun$5 diff --git a/tests/debug-preview/eval-in-for-comprehension.scala b/tests/debug-preview/eval-in-for-comprehension.scala new file mode 100644 index 000000000000..0ea86fbb0302 --- /dev/null +++ b/tests/debug-preview/eval-in-for-comprehension.scala @@ -0,0 +1,14 @@ +object Test: + def main(args: Array[String]): Unit = + val list = List(1) + for + x <- list + y <- list + z = x + y + yield x + for + x <- list + if x == 1 + yield x + for x <- list yield x + for x <- list do println(x) \ No newline at end of file diff --git a/tests/debug/eval-in-for-comprehension.check b/tests/debug/eval-in-for-comprehension.check index 6e91c891ebdb..fb0d62135efb 100644 --- a/tests/debug/eval-in-for-comprehension.check +++ b/tests/debug/eval-in-for-comprehension.check @@ -8,9 +8,16 @@ eval list(0) result 1 eval x result 1 +break Test$ 6 // in main$$anonfun$1$$anonfun$adapted$1 break Test$ 7 // in main$$anonfun$1$$anonfun$1 eval x + y result 2 +// TODO this line position does not make any sense +break Test$ 6 // in main$$anonfun$1$$anonfun$1 +break Test$ 7 // in main$$anonfun$1$$anonfun$1 +break Test$ 6 // in main$$anonfun$1$$anonfun$2 +break Test$ 6 // in main$$anonfun$1$$anonfun$2 +break Test$ 7 // in main$$anonfun$1$$anonfun$2 break Test$ 11 // in main$$anonfun$2 eval x From 49bc04dfe5f9b93312be58d6fd7b15aa280ffa8a Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Wed, 12 Mar 2025 09:22:02 +0100 Subject: [PATCH 5/5] Adjust failing SemanticdbTests when compiling without -preview --- .../expect/ForComprehension.expect.scala | 52 ++++++------- tests/semanticdb/metac.expect | 77 ++++++++++--------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/tests/semanticdb/expect/ForComprehension.expect.scala b/tests/semanticdb/expect/ForComprehension.expect.scala index 864a87c6717c..815b7a93518d 100644 --- a/tests/semanticdb/expect/ForComprehension.expect.scala +++ b/tests/semanticdb/expect/ForComprehension.expect.scala @@ -3,43 +3,43 @@ package example class ForComprehension/*<-example::ForComprehension#*/ { for { a/*<-local0*/ <- List/*->scala::package.List.*/(1) - b/*<-local1*/ <- List/*->scala::package.List.*/(1) + b/*<-local1*//*->local1*/ <- List/*->scala::package.List.*/(1) if b/*->local1*/ >/*->scala::Int#`>`(+3).*/ 1 - c/*<-local2*/ = a/*->local0*/ +/*->scala::Int#`+`(+4).*/ b/*->local1*/ + c/*<-local2*//*->local2*/ = a/*->local0*/ +/*->scala::Int#`+`(+4).*/ b/*->local1*/ } yield (a/*->local0*/, b/*->local1*/, c/*->local2*/) for { - a/*<-local3*/ <- List/*->scala::package.List.*/(1) - b/*<-local4*/ <- List/*->scala::package.List.*/(a/*->local3*/) + a/*<-local4*/ <- List/*->scala::package.List.*/(1) + b/*<-local5*/ <- List/*->scala::package.List.*/(a/*->local4*/) if ( - a/*->local3*/, - b/*->local4*/ + a/*->local4*/, + b/*->local5*/ ) ==/*->scala::Any#`==`().*/ (1, 2) ( - c/*<-local6*/, - d/*<-local7*/ - ) <- List/*->scala::package.List.*/((a/*->local3*/, b/*->local4*/)) + c/*<-local7*/, + d/*<-local8*/ + ) <- List/*->scala::package.List.*/((a/*->local4*/, b/*->local5*/)) if ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/ + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/ ) ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) - e/*<-local8*//*->local8*/ = ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/ + e/*<-local9*//*->local9*/ = ( + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/ ) - if e/*->local8*/ ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) - f/*<-local9*/ <- List/*->scala::package.List.*/(e/*->local8*/) + if e/*->local9*/ ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) + f/*<-local10*/ <- List/*->scala::package.List.*/(e/*->local9*/) } yield { ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/, - e/*->local8*/, - f/*->local9*/ + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/, + e/*->local9*/, + f/*->local10*/ ) } } diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index c5bb4e645967..f674c6fb4159 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -1661,8 +1661,8 @@ Schema => SemanticDB v4 Uri => ForComprehension.scala Text => empty Language => Scala -Symbols => 12 entries -Occurrences => 51 entries +Symbols => 13 entries +Occurrences => 53 entries Synthetics => 6 entries Symbols: @@ -1671,13 +1671,14 @@ example/ForComprehension#``(). => primary ctor (): ForComprehension local0 => param a: Int local1 => param b: Int local2 => val local c: Int -local3 => param a: Int -local4 => param b: Int -local5 => param x$1: Tuple2[Int, Int] -local6 => val local c: Int -local7 => val local d: Int -local8 => val local e: Tuple4[Int, Int, Int, Int] -local9 => param f: Tuple4[Int, Int, Int, Int] +local3 => param x$1: Tuple2[Int, Int] +local4 => param a: Int +local5 => param b: Int +local6 => param x$1: Tuple2[Int, Int] +local7 => val local c: Int +local8 => val local d: Int +local9 => val local e: Tuple4[Int, Int, Int, Int] +local10 => param f: Tuple4[Int, Int, Int, Int] Occurrences: [0:8..0:15): example <- example/ @@ -1686,51 +1687,53 @@ Occurrences: [4:4..4:5): a <- local0 [4:9..4:13): List -> scala/package.List. [5:4..5:5): b <- local1 +[5:4..5:5): b -> local1 [5:9..5:13): List -> scala/package.List. [6:7..6:8): b -> local1 [6:9..6:10): > -> scala/Int#`>`(+3). [7:4..7:5): c <- local2 +[7:4..7:5): c -> local2 [7:8..7:9): a -> local0 [7:10..7:11): + -> scala/Int#`+`(+4). [7:12..7:13): b -> local1 [8:11..8:12): a -> local0 [8:14..8:15): b -> local1 [8:17..8:18): c -> local2 -[10:4..10:5): a <- local3 +[10:4..10:5): a <- local4 [10:9..10:13): List -> scala/package.List. -[11:4..11:5): b <- local4 +[11:4..11:5): b <- local5 [11:9..11:13): List -> scala/package.List. -[11:14..11:15): a -> local3 -[13:6..13:7): a -> local3 -[14:6..14:7): b -> local4 +[11:14..11:15): a -> local4 +[13:6..13:7): a -> local4 +[14:6..14:7): b -> local5 [15:6..15:8): == -> scala/Any#`==`(). -[17:6..17:7): c <- local6 -[18:6..18:7): d <- local7 +[17:6..17:7): c <- local7 +[18:6..18:7): d <- local8 [19:9..19:13): List -> scala/package.List. -[19:15..19:16): a -> local3 -[19:18..19:19): b -> local4 -[21:6..21:7): a -> local3 -[22:6..22:7): b -> local4 -[23:6..23:7): c -> local6 -[24:6..24:7): d -> local7 +[19:15..19:16): a -> local4 +[19:18..19:19): b -> local5 +[21:6..21:7): a -> local4 +[22:6..22:7): b -> local5 +[23:6..23:7): c -> local7 +[24:6..24:7): d -> local8 [25:6..25:8): == -> scala/Any#`==`(). -[26:4..26:5): e <- local8 -[26:4..26:5): e -> local8 -[27:6..27:7): a -> local3 -[28:6..28:7): b -> local4 -[29:6..29:7): c -> local6 -[30:6..30:7): d -> local7 -[32:7..32:8): e -> local8 +[26:4..26:5): e <- local9 +[26:4..26:5): e -> local9 +[27:6..27:7): a -> local4 +[28:6..28:7): b -> local5 +[29:6..29:7): c -> local7 +[30:6..30:7): d -> local8 +[32:7..32:8): e -> local9 [32:9..32:11): == -> scala/Any#`==`(). -[33:4..33:5): f <- local9 +[33:4..33:5): f <- local10 [33:9..33:13): List -> scala/package.List. -[33:14..33:15): e -> local8 -[36:6..36:7): a -> local3 -[37:6..37:7): b -> local4 -[38:6..38:7): c -> local6 -[39:6..39:7): d -> local7 -[40:6..40:7): e -> local8 -[41:6..41:7): f -> local9 +[33:14..33:15): e -> local9 +[36:6..36:7): a -> local4 +[37:6..37:7): b -> local5 +[38:6..38:7): c -> local7 +[39:6..39:7): d -> local8 +[40:6..40:7): e -> local9 +[41:6..41:7): f -> local10 Synthetics: [4:9..4:13):List => *.apply[Int]