Private setters on properties bypassed?

I’m trying to reacquaint myself with Kotlin after some years of not using it, and have come across some behaviour that I don’t understand with private setters on properties. Consider this very simple code:

class Car {
  val fuelConsumption = 10

  var fuel = 100
    private set

  fun travel(distance: Int) {
    fuel -= fuelConsumption * distance
  }
}

fun main() {
  val car = Car()
  println("Initial fuel: ${car.fuel}")  // prints 100
  println("Travelling...")
  car.travel(2)
  println("Final fuel: ${car.fuel}")    // prints 80

  //car.fuel = 70     // compiler error if uncommented
  car.fuel -= 10      // no compiler error here
  println(car.fuel)   // prints 70
}

I’m compiling this on the command line with kotlinc-jvm 2.0.0. Direct assignment to the fuel property gives me the expected compiler error, but I don’t understand why use of the -= operator doesn’t give me the same result.

When I examine the resulting JVM bytecode I can see that the compiler is adding a static method with this signature to the Car class:

public static final void access$setFuel$p(Car, int);

If I comment out the line using the -= operator, this static method no longer features in the bytecode.

The static method also disappears if I move main() to a separate .kt file. In this case, both files will compile successfully but when I run the program I get a NoSuchMethodError exception, referring to that now missing static method.

I’m probably missing something obvious here, but if anyone can offer any insight it would be much appreciated!

Kotlin 2.0 has a new compiler that may still have bugs.

I’d suggest trying your code on 1.9 if you can — and if that works, then raising a bug on the official bug tracker.

(Or if it doesn’t work on 1.9, then I too am missing something!)

3 Likes

Yeah, looks like its a regression in the new compiler; 1.9 gives the expected error message.

I’ve submitted a bug report.

2 Likes