1

I came across this type mismatch that I don't understand:

error: type mismatch;
found   : org.fluentlenium.core.domain.FluentList[_<:org.fluentlenium.core.domain.FluentWebElement]
required: org.fluentlenium.core.domain.FluentList[?0(in value $anonfun)] where type ?0(in value $anonfun) <: org.fluentlenium.core.domain.FluentWebElement
Note: org.fluentlenium.core.domain.FluentWebElement >: ?0, but Java-defined class FluentList is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: ?0`. (SLS 3.2.10)

Indeed, it is precised that the "found" value is of type:

org.fluentlenium.core.domain.FluentList[_<:org.fluentlenium.core.domain.FluentWebElement] => variant type parameter

I couldn't represent a situation like this, where a "found" value is a variant type parameter. I tried this simple snippet code:

public class CarList<E extends Car> implements Collection<E> { // written in Java
   //overriden methods from Collection here
}

public class Car{} // written in Java

public Ferrari extends Car{} //written in Java

object Main extends App {  

   val carList: CarList[Car] = new CarList[Car]

   val l: CarList[Ferrari] = carList

}

Compilation Error occuring is very similar:

error: type mismatch;
found   : app.CarList[app.Car]     //but in this case, logically it's an invariant type: Car
required: app.CarList[app.Ferrari]
Note: app.Car >: app.Ferrari, but Java-defined class CarList is invariant in type E.
You may wish to investigate a wildcard type such as `_ >: app.Ferrari`. (SLS 3.2.10)
val l: CarList[Ferrari] = carList
                                     ^

How to modify my code snippet to end up exactly with:

  • the same kind of error than FluentList's one (precising a variant type parameter in the "found" value):
    found : app.CarList[_ :> app.Car]
  • with the same advice from compiler:
    You may wish to investigate a wildcard type such as _ >:

so that I can figure out what might be the origin of the issue?

Mik378
  • 21,881
  • 15
  • 82
  • 180

1 Answers1

0

In your java example it seems you have reversed two things. You can not assign a list of cars to a list of Ferraris.

With that in mind I interpreted the snippet like this:

class CarList[E <: Car]

class Car
class Ferrari extends Car

object Main extends App {

  val carList = new CarList[Ferrari]

  // this now throws a compiler error
  val l: CarList[Car] = carList
}

The compiler error is as follows:

type mismatch;
found: CarList[Ferrari] required: CarList[Car]
Note: Ferrari <: Car, but class CarList is invariant in type E.
You may wish to define E as +E instead.

So the compiler actually helps us. This definition:

class CarList[E <: Car]

tells the compiler we have a list of things that extend Car.

However, that doesn't tell the compiler that CarList[Ferrari] also extends CarList[Car]. In order to tell the compiler that's the case we need to make E covariant with +.

Thus to solve the error we could do two things:

  1. Define CarList as CarList[+E], saying you don't care what's in them, but if A extends B then CarList[A] can be considered to extend CarList[B]
  2. Define CarList as CarList[+E <: Car], saying the same as 1. but with the extra restraint on the type of E in that it must be a Car.

This question about variance might give additional information.

Community
  • 1
  • 1
EECOLOR
  • 11,184
  • 3
  • 41
  • 75
  • Sorry but my question was not: "how to solve it?" since I well master covariance/contravariance. My question was: "How to modify my code snippet to end up exactly with the same kind of error?", meaning I would like to come across an error informing: "found : `app.CarList[_ <: app.Car] // I would like to come across this line required: app.CarList[app.Ferrari] Note: app.Car >: app.Ferrari, but Java-defined class CarList is invariant in type E. You may wish to investigate a wildcard type such as `_ >: app.Ferrari`. (SLS 3.2.10)` I want to see a "found" with a variant parameter `:>` – Mik378 Feb 20 '13 at 22:17
  • You are totally right. I read the question wrong. Interesting question though! – EECOLOR Feb 20 '13 at 22:35
  • No problem :) I spent all day long to search for an explanation ... I can't see one :( – Mik378 Feb 20 '13 at 22:38
  • You can easily reproduce this issue. You may look at my previous post here: http://stackoverflow.com/questions/14970301/error-using-specs2-with-fluentlenium-api . Whatever the "Specs2" Matcher used, error occurs; for instance: `browser.find(".myClass").find("#mySubElement") must_==(null)`. Solving it is pretty easy but figuring out WHY is another game :) – Mik378 Feb 20 '13 at 22:51
  • Damn, that took away the rest of my evening, haha. I could not reproduce that either. The wildcard error that you get with this snippet: `val x:CarList[_ <: Car] = (???):CarList[_ >: Car] ` is very similar. To get the error the other way around `_ <: Car` is doable as well. Apparently you found a construction were a type is both `CarList[X <: Car]` and `CarList[X >: Car]`. I don't know the precedence rules for the compiler, but it's showing information from the last one of these types. – EECOLOR Feb 21 '13 at 07:35
  • :) I would say one thing: "Compiler, please blow into the breathalyser" ;) – Mik378 Feb 21 '13 at 10:24