The top answer of this question explains why method arguments are contravariant. The author says that if this would compile:
case class ListNode[+T](h: T, t: ListNode[T]) {
  def head: T = h
  def tail: ListNode[T] = t
  def prepend(elem: T): ListNode[T] =
    ListNode(elem, this)
}
Then this would be okay:
val list1: ListNode[String] = ListNode("abc", null)
val list2: ListNode[Any] = list1  // list2 and list1 are the same thing
val list3: ListNode[Int] = list2.prepend(1) // def prepend(elem: T): ListNode[T]
Note that I have removed the last row of the original snippet.
My thought process is the following:
- On line 1, a 
ListNode[String]calledlist1is assigned a newListNode(someString, null). Nothing strange here.list1is not aListNode[String]. - On line 2, a 
ListNode[Any]gets assignedlist1. This is fine becauseListNodeis covariant andAnyis a supertype ofString. - On line 3, the 
prependmethod oflist2is called. Sincelist2is aListNode[Any],list2.prepend()should return aListNode[Any]. But the result of the method call is assigned to aListNode[Int]. This can not possibly compile becauseIntis a subtype ofAnyandListNodeis NOT contravariant! 
Have I misunderstood something? How can the author claim this would ever compile?