Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scalac gives error found: scala.Boolean(false) required: java.lang.Boolean

Tags:

boolean

scala

The code below checks for basic auth. Here resp is the 401 unauthorized response. I check if an Authorization header is present and if present I verify its value otherwise I call resp:

def validate(authHeader: String): Boolean = {
   //........
} 
val authHeader = Option(request.getHeader("Authorization"))
authHeader match {
  case Some(header) if header.startsWith("Basic ") => validate(header) match { case false => resp }
  case _ => resp
}

When I compile it, it gives error for line match { case false => resp } saying found: scala.Boolean(false) required: java.lang.Boolean. I am confused about why its treating scala Boolean different from java Boolean.

I noticed there was a line import java.lang._ at the beginning of the file (I don't know why). I commented it out and the code give a warning instead of an error:

warning: match may not be exhaustive.
It would fail on the following input: true

I think this is because I didn't write the case true. But what made the original error happen, and why does it only happen with import java.lang._?

EDIT:

Here is a minimal example for the problem:

val f: java.lang.Boolean = false
val f2: scala.Boolean = false

/* The following line produces this error:
error: type mismatch;
 found   : scala.Boolean(false)
 required: java.lang.Boolean
*/
f match { case false => 5 }

/* The following line produces this warning:
warning: match may not be exhaustive.
It would fail on the following input: true
*/
f2 match { case false => 5 }
like image 421
lovesh Avatar asked May 06 '14 14:05

lovesh


People also ask

What is Boolean in scala?

Boolean (equivalent to Java's boolean primitive type) is a subtype of scala. AnyVal. Instances of Boolean are not represented by an object in the underlying runtime system. There is an implicit conversion from scala.

Can Boolean be null scala?

Nullable boolean can be null, or having a value “true” or “false”. Before accessing the value, we should verify if the variable is null or not. This can be done with the classical check : if … else …


1 Answers

It seems that implicit conversions are not in effect in the case of pattern matching.

Consider:

scala> case class Foo(x: Int)
defined class Foo

scala> case class Bar(x: Int)
defined class Bar

scala> implicit def foo2bar(x: Foo) = Bar(x.x)
foo2bar: (x: Foo)Bar

scala> Foo(3) match { case Foo(3) => 3; case _ => 4 }
res19: Int = 3

scala> Foo(3) match { case Bar(3) => 3; case _ => 4 }
<console>:14: error: constructor cannot be instantiated to expected type;
 found   : Bar
 required: Foo
              Foo(3) match { case Bar(3) => 3; case _ => 4 }
                                  ^

Compare with:

scala> val f: java.lang.Boolean = false
f: Boolean = false

scala> f.<TAB>
asInstanceOf   booleanValue   compareTo      isInstanceOf   toString       

scala> f || true
res21: Boolean = true

implicit conversions worked here, but not here:

scala> f match { case false => 3; case true => 4 }
<console>:15: error: type mismatch;
 found   : scala.Boolean(false)
 required: java.lang.Boolean
              f match { case false => 3; case true => 4 }
                             ^
<console>:15: error: type mismatch;
 found   : scala.Boolean(true)
 required: java.lang.Boolean
              f match { case false => 3; case true => 4 }
                                              ^

I agree that this is quite counterintuitive but I doubt it could be fixed without introducing a special casing to the language, or making scalac somehow recognize pattern matches where all patterns belong to a single type, and try to find an implicit conversion to that type. The workaround would be to do an explicit asInstanceOf[Boolean] cast. Although it's odd that the following works fine:

scala> "foobar".startsWith("foo") match { case true => 3 ; case false => 4 }
res26: Int = 3
like image 62
Erik Kaplun Avatar answered Oct 03 '22 22:10

Erik Kaplun