Search code examples
javascalarmi

@remote annotation in Scala type mismatch


My trait:

@remote trait Computer {
  def execute(task: Task[Any]): Any
}

Snippet of main class in a companion object of a class ComputerImpl that implements Computer simply by defining execute to be = task.execute().

val name = "Computer"
val engine: Computer = new ComputerImpl()
val stub = UnicastRemoteObject.exportObject(engine, 0).asInstanceOf[Computer]

I get this error:

system/ComputerImpl.scala:19: error: type mismatch;
 found   : api.Computer
 required: java.rmi.Remote
      val stub = UnicastRemoteObject.exportObject(engine, 0).asInstanceOf[Computer]

It goes away if I do the more explicit trait Computer extends Remote but in "Scala for Impatient" it says "Scala uses annotations @cloneable and @remote instead of the Cloneable and java.rmi.Remote interfaces for cloneable and remote object."

What is going wrong?


Solution

  • This looks as if it should work, but this is a compilation phase problem. The compiler is applying the @remote, that is adding in the interface to the trait definition, after it's done the type checking for the compilation. However, the following works:

    val stub = UnicastRemoteObject.exportObject(engine.asInstanceOf[java.rmi.Remote], 0).asInstanceOf[Computer]
    

    but it's a bit ugly.

    EDIT: It's failing in the typer compilation phase, whereas it looks like the @remote substitution is being done in the jvm phase, which is after the typer phase.

    And in fact, this is a known issue, type inference fails with @remote annotation. From there, Martin Odersky says:

    That's completely as speced. @remote is not the same as `extends Remote' for the type checker.

    There is no further explanation, but I wouldn't hold your breath for a compiler solution :-)