-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2.12] Improve -Yrepl-class-based #8712
Conversation
ee22df6
to
ef71699
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gave it a glance.
In retronym/spark#1, I've setup the Spark Maven build to be able to test against the Scala release from this (or any) PR, figured out how to run the Spark REPL test suite, and found that we need to add |
I'd prefer if we didn't require Spark to pass We could enable it by default if |
/cc @srowen (from the Spark team) |
Do you know why, what change "broke" plain |
…ores some imports Co-authored-by: Dale Wijnand <[email protected]>
Always generate a `val INSTANCE` field, whether it's for class-based or object-based, so that the access code branches needn't branch on isClassBased. This greatly simplifies the next commit, for handling value classes.
... by making any code snippet that defines (or seems to define) a value class use the original "object-based" wrappers instead.
Co-authored-by: Dale Wijnand <[email protected]>
This avoids problems like private value read escapes its defining scope as part of type u.Type when running `test/files/run/class-symbol-contravariant.scala` (and a few others) with -Yrepl-class-based. Also add a test specific for type aliases, extracted from `test/files/jvm/interpreter.scala`, to run in class-based mode.
e77dbd9
to
5835734
Compare
The Spark REPL uses -Yrepl-class-based and the change around ImportHandler in interpreter/Imports (and that introduced the custom wrapperCleanup phase for the REPL) requires -Yrepl-use-magic-imports be set in order for the Spark REPL to continue to work correctly. Rather than affect all existing Spark releases that choose to upgrade Scala, we preserve the functioning of the Spark REPL by enabling "magic imports" when using the class-based wrappers.
... and thus -Yrepl-use-magic-imports too.
The intent is for these to be true, but we'll do that for 2.13.x, not 2.12.x.
5835734
to
97b5834
Compare
It will be the removal of the heuristic that ignores imports introduced by previous lines for when the current line contains a class definitions that doesn't include an identifier contributed by that import. That was supposed to be okay for us to remove because the new dead back-reference elimination (DBRE) should detect that its unused and kill it. The use case is covered in Indeed, that test fails with - at scala.tools.partest.nest.StreamCapture$.$anonfun$capturingOutErr$2(StreamCapture.scala:32)
diff --git a/test/files/run/repl-serialization.scala b/test/files/run/repl-serialization.scala
index a0fed0b6f4..2f201146c2 100644
--- a/test/files/run/repl-serialization.scala
+++ b/test/files/run/repl-serialization.scala
@@ -14,7 +14,7 @@ object Test {
def run(): Unit = {
val settings = new Settings()
settings.Yreplclassbased.value = true
- settings.YreplMagicImport.value = true
+ settings.YreplMagicImport.value = false
//settings.Xprint.value = List("refchecks","wrapper-cleanup")
settings.usejavacp.value = true
I'll take a quick look and see if the if its an easy or hard problem to solve. |
|
I pushed a fix. The main problem was that the We no longer need to auto-enable |
This comment has been minimized.
This comment has been minimized.
I've pushed a small refinement -- we should not run the unused analysis on the each |
I also pushed a commit to limit the unsed private removal to That last part aims to centralize the logic for creating the REPL temp val names and checking if symbol has such a name. It then aims to limit the unused private removal to such vals, as we don't have any business removing unsed privates from user code. |
9659930
to
fd6f95c
Compare
- Only run the transform under `-Yrepl-class-based` - Only eliminate the `$lineXY$read` fields and accessors to be sure we don't accidentally eliminate statically unused user code, which could be intended for reflective use or the like. - Colocate the logic that creates and tests for `$lineXY$read` val names.
fd6f95c
to
1dc6d84
Compare
Spark REPL test suite is happy with this PR now. I dropped the my commit that explicitly enabled
|
Also passes with: diff --git a/repl/src/main/scala/org/apache/spark/repl/Main.scala b/repl/src/main/scala/org/apache/spark/repl/Main.scala
index a68b112ed2..8f90d2b07e 100644
--- a/repl/src/main/scala/org/apache/spark/repl/Main.scala
+++ b/repl/src/main/scala/org/apache/spark/repl/Main.scala
@@ -67,20 +67,22 @@ object Main extends Logging {
.mkString(File.pathSeparator)
val interpArguments = List(
"-Yrepl-class-based",
"-Yrepl-outdir", s"${outputDir.getAbsolutePath}",
"-classpath", jars
) ++ args.toList
val settings = new GenericRunnerSettings(scalaOptionError)
settings.processArguments(interpArguments, true)
+ settings.processArguments("-Yrepl-use-magic-imports:false" :: Nil, processAll = false)
+ |
I'lm pretty sure we no longer need to customised `ignoreNames` now that we're customizing `isEffectivelyPrivate` and we're restricting the unused decl dropping to trees of the form `val $lineXY$read = ...`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Should we disable the postSetHook
that enables magic imports?
This reverts commit c5f1424.
4aa17e4
to
eae60b9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should help ensure the order is as deterministic as possible.
@dwijnand tentatively labeled with "release-notes", but actually I'm unsure what the takeaway here is for users. I'd suggest either removing the label, or improving the PR description to begin with a user-focused description that puts this change in context, with the contributor-focused info afterwards. |
For Spark, is the takeaway that |
@srowen No, that's no longer true, thankfully (it's why we were able to drop the postSetHook). The Spark-specific takeaway is we tweaked how to minimise references, so that Spark's serialisation continues to work (aka not regressing on https://issues.apache.org/jira/browse/SPARK-2576 and https://issues.apache.org/jira/browse/SPARK-2632), while fixing https://issues.apache.org/jira/browse/SPARK-5150. Tested with our If you could double-check that for us, using the https://scala-ci.typesafe.com/artifactory/scala-integration/org/scala-lang/scala-compiler/2.12.11-bin-4c726db/ that would be great! |
@SethTisue I'll update the description. It won't be interesting for non-Spark users until 2.13.2, but we can still describe it here and reference to it. |
These changes improve the REPL under
-Yrepl-class-based
, so that it eventually it will become the new default (in 2.13.2).For background:
-Yrepl-class-based
is an experimental (-Y
) compiler option that switches the REPL to use "class-based" (instead of "object-based") wrappers, as its implementation detail. This mode originated in Spark's fork of the Scala REPL (and was later contributed upstream toscala/scala
) as the object-based wrappers were problematic for the code serialisation that the Spark REPL does.Additionally, the change in encoding to Scala's lambdas that happened in Scala 2.12 (i.e. since targeting JDK 8+) made it much, much easier to cause a deadlock in the REPL, aka scala/bug#9076. Using class-based wrappers resolves this too.
However, there were some limitations to the class-based wrappers' implementation, that have been addressed with this PR.
The first is the most involved part of this change. The mode contained a heuristic that an import from previous lines would be ignored if the current line contained a class definition
C
and the import didn't contribute a name that was among the identifiers on this line. The goal of this heuristic was to avoid the outer pointer of classC
transitively capturing theiw$
wrappers with state from previous lines that wasn't actually referred to. However, these imports could contribute implicits which are needed during typechecking of the class, so the heuristic changed semantics w.r.t-Yrepl-class-based:false
(reported as SPARK-5150). This PR always considers the imports, but adds a post-processing step to prune out unused references to the state of prior lines.The mode can now handle value classes, by switching the evaluation to use the old, object-based wrappers for the snippet that defines a value class.
The mode now mitigates any attempts to define a macro in the REPL, by giving the user some more information in the error message.
Refs scala/bug#9076
Refs SPARK-5150
TODOs:
-Yrepl-class-based
already