我可以更改scala中编译器给出的错误消息吗?

时间:2015-12-08 10:47:22

标签: scala compiler-errors

我有密钥和正文案例类。假设密钥扩展了Key特征,并且正文扩展了Body特征。对于每个键,只有一个给定的体型。下面,我试图以编译器可以为我检查它的方式编程,它甚至似乎工作!

trait Key [T <: Body]
trait Body

case class Body1 () extends Body
case class Body2 () extends Body

case class Key1 () extends Key[Body1]
case class Key2 () extends Key[Body2]

object Tester {
  def func[T <: Body](key: Key[T], body: T) = {
    println("Key: "+ key, "Body: "+body)
  }

  val k1 = Key1()
  val b1 = Body1()
  val b2 = Body2()
  func(k1, b1)  // good match
  func(k1, b2)  // wrong match
}

如我所愿,上面的最后一行给出了编译时错误(见下文)。但是我可以让它更具可读性,以便我的图书馆用户能够理解正在发生的事情吗?特别是,最后的“提示”在我的案例中具有误导性。

Error:(18, 9) type mismatch;
 found   : A$A60.this.Key1
 required: A$A60.this.Key[Product with Serializable with A$A60.this.Body]
Note: A$A60.this.Body1 <: Product with Serializable with A$A60.this.Body (and A$A60.this.Key1 <: A$A60.this.Key[A$A60.this.Body1]), but trait Key is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
  func(k1, b2)
       ^

1 个答案:

答案 0 :(得分:1)

使用implicitNotFound可以更改编译信息

import scala.annotation.implicitNotFound

trait Key[T <: Body]    
trait Body

case class Body1() extends Body    
case class Body2() extends Body

case class Key1() extends Key[Body1]    
case class Key2() extends Key[Body2]

@implicitNotFound("Expected ${From}, but found ${To}.")
class CompileMsg[From, To]

object CompileMsg {
  implicit def implValue[T] = new CompileMsg[T, T]
}

object Tester {
  def func[KeyBody <: Body, BodyBody <: Body]
  (key: Key[KeyBody], body: BodyBody)
  (implicit msg: CompileMsg[KeyBody, BodyBody]) = {
    println("Key: " + key, "Body: " + body)
  }

  val k1: Key1  = Key1()
  val b1        = Body1()
  val b2: Body2 = Body2()
  func(k1, b1) // good match
  func(k1, b2) // wrong match
}

现在,为您提供以下错误消息:

Error:(35, 8) keyBody is A$A57.this.Body1 != A$A57.this.Body2
func(k1, b2) // wrong match
^