Scala 2.12.15 - no type error despite mismatch

Hello, simplified REPL sample (Scastie):

$  scala
Welcome to Scala 2.13.6 (OpenJDK 64-Bit Server VM, Java 1.8.0_302).
Type in expressions for evaluation. Or try :help.
scala> def cond = false
def cond: Boolean

scala> def test = for {
     |   () <- cond match {
     |     case true => Some(()) // : Option[Unit]
     |     case false => Some(Seq((), ())) // : Option[Seq[Unit]]
     |   }
     | } yield ()
def test: Option[Unit]

scala> test
val res0: Option[Unit] = None

This is not yielding any compile error despite the branches of the pattern match having different types. Perhaps even more surprising, the final result is None despite both branches being Some. Is this a known behaviour? Seems like a bug to me.

Thanks to Any and covariance, the LUB of both branches is Option[Any].

Perhaps even more surprising, the final result is None despite both branches being Some

That is because the result of the code didn’t matched the filter, thus the end result is None

Is similar to this:

for {
  x <- (foo: Option[Int]
  if x == 0
} yield 3

If x is not 0 then it will return None
Note that the above code can be written like:

for {
  0 <- (foo: Option[Int]
} yield 3

Which is exactly what you did.

Seems like a bug to me.

There is a compiler flag to warn when the compiler infers Any which helps with these kind of situations.

1 Like

Thanks, that makes sense. From Scala Compiler Options | Scala Documentation , it’s not clear what Scala version that lint is for. E.g. I’ve enabled -Xlint in my sbt config, which to my understanding should enable all the lints, but there’s no warning from the compiler. Using -Xlint:infer-any directly has no effect either.

EDIT: running the above example code with scala -Xlint:infer-any does not yield any warning either.

I personally use sbt-tpolecat which enables all warnings for me so not exactly sure how to do it.

Hopefully, someone would be able to provide an answer that doesn’t require a third-party tool.

1 Like