scalamavenscalac

How to make the scala compiler find case classes used with wrong arguments


I have a case class Disconnect(nodeId: PublicKey) that has 1 parameter in it, however in some other part of the code it happened to be used without the parameter i.e: Disconnect and the compiler did not catch the error, note that I've also tried to run the compiler with -Xlint option and it still can't catch the error.

[history] It used to be case object Disconnect but at some point it has been changed to case class and a parameter was added, in the code it was still instantiated parameterless and the compiler couldn't notice it. I tried adding -Xlint option to the compiler but it didn't help.

In Peer.scala

  object Peer { 
    // other code
    case class Disconnect(nodeId: PublicKey)
    // more code
  }  

In Channel.scala

  // inside a function
  revocationTimeout.peer ! Peer.Disconnect
  //

I expected the compiler to catch the misuse of the case class and fail to compile.

Edit: thanks all for the replies, indeed the compiler is doing his job just fine and Disconnect is being used as a type instead of case class instance, this is possible because it's used in a function that accepts Any as parameter.


Solution

  • Since you declare Disconnect to be a case class, the compiler automatically generates a companion object Disconnect, which holds all the neat apply and unapply methods. Therefore, Peer.Disconnect is a perfectly valid expression of the singleton type Peer.Disconnect.type. One might argue that it wouldn't have happened if you used Akka Typed right from the beginning, but in your code, the ! method accepts anything, so in order to force the compiler to emit some meaningful error messages, you need something else. Here is one simple approach:

    1. Revert to the state where Disconnect was a singleton object, without an associated case class.
    2. Remove the Disconnect definition altogether. Add case class NewDisconnect instead. Now every occurrence of Peer.Disconnect will become a proper error.
    3. Replace all Peer.Disconnect by Peer.NewDisconnect(foo)
    4. Rename NewDisconnect to Disconnect.