When I run the code below,
class A(private[this] var i: Int) {
  println("i = " + i)
  i -= 1
  println("After decrement, i = " + i)
  override def toString = i.toString
}
object A extends App {
  val a = new A(1)
  println("a = " + a)
}
I get:
i = 1
After decrement, i = 0
a = 1
If I replace private[this] by private, I get the expected behavior, i.e. the last output line becomes a = 0. I'm using IntelliJ 2016.1.2, Scala plugin version 3.0.6., and scala-sdk-2.11.8.
It's a bug. See SI-6880.
private[this] on a constructor var causes it to mistakenly shadow itself, and you get the original value instead of the accessor you want. 
Yes, it's a bug (SI-6165, SI-6880).
Let's explore further. This is the decompiled code for both cases:
private[this]:
class A extends Object {
  <paramaccessor> private[this] var i: Int = _;
  override def toString(): String = scala.Int.box(A.this.i).toString();
  def <init>(i: Int): com.yuval.A = {
    A.this.i = i;
    A.super.<init>();
    scala.this.Predef.println("i = ".+(scala.Int.box(i)));
    i = i.-(1);
    scala.this.Predef.println("After decrement, i = ".+(scala.Int.box(i)));
    ()
  }
};
Here, we see that var i is created for the object and is accessed directly in the code. We see that i is assigned to A.this.i, which is a direct assignment to the field. Later, the mutated value is assigned to i, the method argument, not to A.this.i, the field of class A. The actual value i is being shadowed.
On the contrary, when i is private:
class A extends Object {
  <paramaccessor> private[this] var i: Int = _;
  <accessor> <paramaccessor> private def i(): Int = A.this.i;
  <accessor> <paramaccessor> private def i_=(x$1: Int): Unit = A.this.i = x$1;
  override def toString(): String = scala.Int.box(A.this.i()).toString();
    def <init>(i: Int): com.yuval.A = {
      A.this.i = i;
      A.super.<init>();
      scala.this.Predef.println("i = ".+(scala.Int.box(A.this.i())));
      A.this.i_=(A.this.i().-(1));
      scala.this.Predef.println("After decrement, i = ".+(scala.Int.box(A.this.i())));
      ()
    }
};
Here, we see that i has a getter and setter methods, unlike private[this]. We also see that the decrement is being done on A.this.i_, which is the setter for the field member A.this.i.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With