Skip to content

SI-9076 REPL wrap is App#4311

Closed
som-snytt wants to merge 3 commits intoscala:2.11.xfrom
som-snytt:issue/9076-b
Closed

SI-9076 REPL wrap is App#4311
som-snytt wants to merge 3 commits intoscala:2.11.xfrom
som-snytt:issue/9076-b

Conversation

@som-snytt
Copy link
Contributor

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.

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>();
      ()
    };
    lazy private[this] var $result: Int = _;
    <stable> <accessor> lazy def $result: Int = {
      $eval.this.$result = $line3.$read.$iw.res0;
      $eval.this.$result
    };
    lazy private[this] var $print: String = _;
    <stable> <accessor> lazy def $print: String = {
      $eval.this.$print = {
        $line3.$read.$iw.main(null);
        "res0: Int = ".+(scala.runtime.ScalaRunTime.replStringOf($line3.$read.$iw.res0, 1000))
      };
      $eval.this.$print
    }
  }
}

res0: Int = 42

@scala-jenkins scala-jenkins added this to the 2.11.6 milestone Feb 10, 2015
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

```
@som-snytt
Copy link
Contributor Author

Second test changed the flag; now the flag is correctly set for the repl session test.

Also rebased.

`-Yrepl-wrap:object` is the default.
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, I'm hesitant to risk breaking those that embedded the repl in 2.11.x

@adriaanm adriaanm closed this Feb 19, 2015
som-snytt added a commit to som-snytt/scala that referenced this pull request Jun 17, 2016
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
som-snytt added a commit to som-snytt/scala that referenced this pull request Aug 16, 2016
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
som-snytt added a commit to som-snytt/scala that referenced this pull request Jan 31, 2017
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
som-snytt added a commit to som-snytt/scala that referenced this pull request Apr 13, 2017
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
adriaanm pushed a commit to adriaanm/scala that referenced this pull request Apr 28, 2017
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
retronym pushed a commit to retronym/scala that referenced this pull request Dec 2, 2019
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
@som-snytt som-snytt deleted the issue/9076-b branch December 19, 2020 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants