"type mismatch" error I don't understand

I use mockito-scala to mock a Java method which return type is Comparable[_] and which uses null as a valid return value.

The signature of the method I want to mock:

Comparable getProperty(@NotNull final String propertyName);

The code snippet where I attempt the mocking:

val entity = mock[Entity]
val comparableNull: Comparable[_] = null
entity.getProperty(EntityMapper.TermEntry.propertyNameDefinition) returns comparableNull

Error I get (in IntelliJ):
Error:(24, 71) type mismatch; found : Comparable[(some other)T(in value <local EntityMapperTest>)] where type (some other)T(in value <local EntityMapperTest>) required: Comparable[T(in value <local EntityMapperTest>)] where type T(in value <local EntityMapperTest>) error after rewriting to EntityMapperTest.this.StubbingOps[Comparable[T]](entity.getProperty(EntityMapper.TermEntry.propertyNameDefinition)).returns.apply possible cause: maybe a wrong Dynamic method signature? entity.getProperty(EntityMapper.TermEntry.propertyNameDefinition) returns value.asInstanceOf[Comparable[_]]

I don’t understand what IntelliJ (or the Scala compiler, for that matter) want to tell me by this.

Side node: Compiler errors in Scala are very often difficult to understand, especially for beginners.

That is an example of where Scala and Java interoperability are still not given.

This Java code uses Comparable which is actually a generic interface Comparable<T>, but here it is used as a raw type.

Broadly speaking, you should not use raw types. See java - What is a raw type and why shouldn't we use it? - Stack Overflow

Your code would compile if you declare the method as

Comparable<Object> getProperty(@NotNull final String propertyName);

and use

entity.getProperty(EntityMapper.TermEntry.propertyNameDefinition) returns null

Maybe you could also get away with using the Java mockito way of mocking or using the non-idiomatic mockito-scala API, but I am not sure.

Note that there were some recent bugs in scala around raw types, particularly in overriding them. I don’t remember the details.

In my opinion, there are different levels of this issue:

  1. The compiler message (I believe IntelliJ provides the raw compiler message) is - in the best case - very difficult to comprehend, if this happens to beginners and I believe there is a great need of improvement-

  2. Most consumers of the API use Kotlin, which does not know about raw types, either. But as far as I understand (my Kotlin knowledge is very limited), Kotlin does the only sane thing: It interprets and handles raw types like Comparable as if it was declared as Comparable<?>.

I don’t think that’s quite true – IntelliJ has its own system, which doesn’t always agree with the real compiler. It’s much better than it used to be, but it’s always worth going to sbt for truth. (I sometimes find the errors I get in sbt a little easier to understand than the ones I see in IntelliJ.)

That said:

Yes, I think most people agree with that. Better error reporting has been a priority of the Dotty / Scala 3 project – they’ve made a good deal of progress, but they’re open to PRs for specific improvements there…

2 Likes

That I did not know that; next time I will look into sbt’s error message. But again, sbt is, in its own way, very obscure to people who are new to Scala.

Well, I have no knowledge in compiler making. I only can provide insight from the perspective of beginners :slight_smile: