"implicit class" doesn't work when expected

I’m wrapping mutable.buffer to provide a Deque, using the normal implicit conversion mechanism. However if I use implicit class Deque in the code below it doesn’t work and I have to use a separate “old style” implicit def BufferToDeque as shown below to to the wrapping, otherwise I get the following comilation error:

Error:(33, 71) value unprepend is not a member of scala.collection.mutable.ListBuffer[Int]
def get$$instance$$res2 = /* ###worksheet### generated $$end$$ */ ab.unprepend()


import scala.collection.{mutable => m}
object Deque {
  import scala.language.higherKinds
  class Deque[E, B[E] <: m.Buffer[E]](buf: B[E]) extends m.ArrayBuffer[E] {
    def unprepend(): E = return buf.remove(0)
    // Additional methods elided
  implicit def BufferToDeque[E, B[E] <: m.Buffer[E]](b: B[E]): Deque.Deque[E, B] = return new Deque(b)

import scala.language.implicitConversions
import Deque._
val b = m.ListBuffer(2,3,4)

The code above works for both ListBuffer and ArrayBuffer and does returns ListBuffer when called on a ListBuffer, even though it extends ArrayBuffer - you have to use ArrayBuffer, you can’t extend Buffer as it’s abstract and you can’t extend ListBuffer as it’s final (why?).

b: scala.collection.mutable.ListBuffer[Int] = ListBuffer(2, 3, 4)
res0: Unit = ()
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(0, 1, 2, 3, 4)
res2: Int = 0
res3: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4)

This works but it’s kinda … unsatisfactory :frowning:

Also, I have a feeling I may be missing a covariance annotation but I’m not sure where it would go…

I confess that I’m not certain, but there are two things that strike me as odd here:

First I don’t know if it’s legal to have an implicit class named Deque inside an object named Deque. It is explicitly not legal to have an implicit class if there is another object of the same name in scope.

Second, and odder, I don’t quite see why Deque extends ArrayBuffer. It is taking the correct buffer as a parameter - what is the extends clause trying to do?

I may be wrong, but it wouldn’t surprise me if one of those is confusing things…

Bingo, you got it, it was the duplicated class names, although you’d never guess it from the compiler error. And yes, the inheritance is bogus as well, I’d been fiddling with this for so long I’d got snow blind. Thanks!