Search code examples
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.

  • scala version: 2.11.12
  • target jvm version: 1.8
  • code compiled with options: -deprecation -feature -language:postfixOps -language:implicitConversions -Xfatal-warnings -unchecked -Xmax-classfile-name 140 -nobootcp

[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.