Conversation
Avoid class initialization traps in the object wrapper by
extending App.
Previously, the following line would hang in the REPL
because the parallel operation was started from the constructor
of the wrapping object, i.e., from the static initializer of
the class. Class-loading the closure would deadlock on loading
the wrapper, which in turn blocks on completion of the par.map.
```
scala> def i = 42 ; List(1, 2, 3).par.map(x => x + i)
```
Any user code that starts a thread could deadlock, including
innocent experiments with Futures in for comprehensions.
The App object is initialized in the usual place, namely
the print method of the eval object, by invoking main.
(A lazy `compute` accommodates two paths of evaluation:
`print` for REPL, `result` for script engine.)
A compiler option `-YreplWrap` takes values "class", "object"
and "app" (default) to select the wrapper template.
```
scala> 42 // show
object $read extends scala.AnyRef {
def <init>() = {
super.<init>;
()
};
object $iw extends App {
def <init>() = {
super.<init>;
()
};
val res0 = 42
};
}
[[syntax trees at end of typer]] // <console>
package $line3 {
object $read extends scala.AnyRef {
def <init>(): $line3.$read.type = {
$read.super.<init>();
()
};
object $iw extends AnyRef with App {
def <init>(): type = {
$iw.super.<init>();
()
};
private[this] val res0: Int = 42;
<stable> <accessor> def res0: Int = $iw.this.res0
}
}
}
[[syntax trees at end of typer]] // <console>
package $line3 {
object $eval extends scala.AnyRef {
def <init>(): $line3.$eval.type = {
$eval.super.<init>();
()
};
<stable> <accessor> lazy def compute: Unit = $line3.$read.$iw.main(null);
lazy private[this] var $result: Int = _;
<stable> <accessor> lazy def $result: Int = {
$eval.this.$result = {
$eval.this.compute;
$line3.$read.$iw.res0
};
$eval.this.$result
};
lazy private[this] var $print: String = _;
<stable> <accessor> lazy def $print: String = {
$eval.this.$print = {
$eval.this.compute;
"res0: Int = ".+(scala.runtime.ScalaRunTime.replStringOf($line3.$read.$iw.res0, 1000))
};
$eval.this.$print
}
}
}
res0: Int = 42
```
f60fc8b to
2da275e
Compare
|
Second test changed the flag; now the flag is correctly set for the repl session test. Also rebased. |
`-Yrepl-wrap:object` is the default.
2da275e to
9277bcd
Compare
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance.
There was a problem hiding this comment.
This is still unconditionally affected. I don't have a good feeling of who might be affected by this, so I'd either move to 2.12 or make all changes to wrapping dependent on -Yrepl-wrap. (Or convince ourselves that it wouldn't affect anyone.)
There was a problem hiding this comment.
I'll move to 2.12. I'm not sure the init line matters, but it does strip a layer of wrapping. Maybe somebody is counting the $iw's somewhere. Nobody's asking for the feature, and by 2.12 everyone will be using worksheet or ammonite, so it really won't matter.
There was a problem hiding this comment.
thanks, I'm hesitant to risk breaking those that embedded the repl in 2.11.x
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Now `valueOfTerm` drills down reflectively using the `fullName` of the desired symbol. It respects a prefix of static modules, but switches to instance mirrors as required. The target is an accessor on the last enclosing instance. cherrypicked from scala#4311 Conflicts: src/repl/scala/tools/nsc/interpreter/IMain.scala
Avoid class initialization traps in the object wrapper by
extending App.
The App object is initialized in the usual place, namely
the print method of the eval object, by invoking main.