Skip to content

Miscompilation: When a try expression mutating a var is lifted, incorrect code is generated #7356

Closed
@smarter

Description

@smarter
object Test {
  def main(args: Array[String]): Unit = {
    var x: String = "foo"
    identity(
      try {
        x = "bar"
      } catch {
        case ex =>
          throw ex
      }
    )
    println(x)
  }
}

This should print bar but it prints foo instead, because the generated code looks like this:

    def main(args: String[]): Unit = 
      {
        var x: String = "foo"
        identity(
          {
            this.liftedTree1(x)
          }
        )
        println(x)
      }
    private final def liftedTree1(x$1: String): 
      scala.runtime.BoxedUnit(scala.runtime.BoxedUnit.UNIT)
     = 
      try 
        {
          {
            x$1 = "bar"
            scala.runtime.BoxedUnit$#UNIT
          }
        }
       catch 
        {
          case ex @ _ => 
            throw ex
        }
  }

This is of course non-sensical (we're mutating a method parameter!) and is detected by the compiler under -Ycheck:all. Either LiftTry needs to be taught to handle vars, or it needs to be moved before CapturedVars.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions