Skip to content

Local optimisations inline too eagerly: System.out is final but can still be mutated by System.setOut #2772

Closed
@smarter

Description

@smarter
import java.io.OutputStream

object Test {
  def main(args: Array[String]): Unit = {
    val oldOut = System.out
    System.setOut(null)
    val a = () => foo(oldOut)
    a()
  }

  def foo(out: OutputStream): Unit = {
    out.write(0)
  }
}

Without -optimise this code works, with -optimise we get a NullPointerException.
Without -optimise:

result of try/inout.scala after genBCode:

package <empty> {
  @scala.annotation.internal.SourceFile("try/inout.scala") final module class 
    Test$
   extends Object { 
    def <init>(): Unit = 
      {
        super()
        ()
      }
    def main(args: String[]): Unit = 
      {
        val oldOut: java.io.PrintStream = System.out
        System.setOut(null)
        val a: Function0 = 
          closure(oldOut | Test.$anonfun$1:scala.compat.java8.JFunction0$mcV$sp)
        {
          a.apply()
          ()
        }
      }
    def foo(out: java.io.OutputStream): Unit = out.write(0)
    private def $anonfun$1(oldOut$1: java.io.PrintStream): Unit = 
      Test.foo(oldOut$1)
  }
  final lazy module val Test: Test$ = new Test$()
}

With -optimise:

result of try/inout.scala after genBCode:

package <empty> {
  @scala.annotation.internal.SourceFile("try/inout.scala") final module class 
    Test$
   extends Object { 
    def <init>(): Unit = 
      {
        super()
        ()
      }
    def main(args: String[]): Unit = 
      {
        System.setOut(null)
        val a: Function0 = 
          closure(Test.$anonfun$1:scala.compat.java8.JFunction0$mcV$sp)
        {
          a.apply()
          ()
        }
      }
    def foo(out: java.io.OutputStream): Unit = out.write(0)
    private def $anonfun$1(): Unit = Test.foo(System.out)
  }
  final lazy module val Test: Test$ = new Test$()
}

Notice that the anonymous function now calls System.out instead of out.

This happened in the Dotty Language Server (https://github.com/lampepfl/dotty/blob/master/language-server/src/dotty/tools/languageserver/Main.scala#L32-L35), the result is that outside projects cannot use the IDE with scalaVersion := 0.2.0-bin-20170614-8ddfcaf-NIGHTLY.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions