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