Reputation: 3858
I have the following function definition in scala:
trait GenExtractor[+R] P
def orElseExtractor[R2<: Super, Super>: R](g: GenExtractor[T, R2]): GenExtractor[T, Super] =
new OrElse[T, Super](this, g)
}
which should combine 2 GenExtractors:
GenExtractor[A]
GenExtractor[B]
into:
GenExtractor[C]
where C is the common supertype of A and B
However, when I try to invoke this function:
val genExtractor = new GenExtractor[R](...parameters...)
val combined = genExtractor.orElseExtractor[Null, R] {
_: FetchedRow => null
}
I got the following error:
Error:(84, 47) type arguments [Null,R] do not conform to method orElseExtractor's type parameter bounds [R2 <: Super,Super >: R]
def orNull: Extractor[R] = orElseExtractor[Null, R] {
^
This is clearly a false alarm since in this case:
type R2 = Null
type Super = R
which fulfil the condition: Null <: R & R >: R
Why is scala compiler gave me this error? What should I do to fix it?
Upvotes: 0
Views: 395
Reputation: 28511
Why would Null
be a subtype of a generic R
? It's not the compiler being off the mark, it's the underlying assumption that Null <: R
is always true. Here are a few fun examples, and they have to do with primitives.
Some(5).orNull
will yield error: Cannot prove that Null <:< Int
Here's your gap, you can try it out in the REPL:
implicitly[Null <:< AnyRef] // will compile
implicitly[Null <:< AnyVal] // blows up, primitives are not included.
In the type system, the supertype of all types, the only thing guaranteed to satisfy any such relationship as you expect it, is scala.Nothing
, not scala.Null
.
null
on the JVM is designed mostly to cope with the absence of type information, not to deal with type system hierarchy. For that you have Nothing
, AnyRef
, AnyVal
and all the other fun stuff.
Upvotes: 3