Option getOrElse type mismatch error

sndyuk picture sndyuk · Nov 1, 2012 · Viewed 10.8k times · Source

Why does this code raise a type mismatch error in Scala 2.9.2? I expected that getOrElse returns type String but actually it returns java.io.Serializable:

scala> implicit def StringToOption(s:String) = Option(s)
StringToOption: (s: String)Option[String]

scala> "a".getOrElse("")
res0: String = a

scala> var opt:Option[String] = "a".getOrElse("")
<console>:8: error: type mismatch;
 found   : java.io.Serializable
 required: Option[String]
       var opt:Option[String] = "a".getOrElse("")
                                             ^

This is OK:

scala> implicit def StringToOption(s:String): Option[String] = Option(s)
StringToOption: (s: String)Option[String]

scala> var b:Option[String] = "a".getOrElse("") toString
b: Option[String] = Some(a)

Answer

Rex Kerr picture Rex Kerr · Nov 1, 2012

It's an unwanted case of incomplete tree traversal. The signature of getOrElse allows type widening, so when it realizes that String is not Option[String] it first tries to fill in a different type ascription on getOrElse, i.e. Serializable. But now it has "a".getOrElse[Serializable]("") and it's stuck--it doesn't realize, I guess, that the problem was making the type too general before checking for implicits.

Once you realize the problem, there's a fix:

"a".getOrElse[String]("")

Now the typer doesn't wander down the let's-widen path, and finds the implicit.