This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Implicits + companion objects

No replies
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Just noticed this in trunk and 2.8.0-beta-prerelease:


test.scala
------------------------------
trait M[A]

trait TestImplicits {
  implicit def makeM[A] = new M[A] {}
}

trait Test {
  def foo[A : M](x : A) = println(implicitly[M[A]].getClass)
}
object Test extends TestImplicits


class Test2 extends Test
object Test2 extends TestImplicits




Console
------------------------------
jsuereth@jsuereth-laptop:~/projects/blog/implicit-subclass$ scalac subclass-test.scala
jsuereth@jsuereth-laptop:~/projects/blog/implicit-subclass$ scala -cp .
Welcome to Scala version 2.8.0.r21454-b20100411185142 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val x = new Test {} 
x: java.lang.Object with Test = $anon$1@19a33662

scala> x.foo(5)            
<console>:7: error: could not find implicit value for evidence parameter of type M[Int]
       x.foo(5)
            ^

scala> val y = new Test2   
y: Test2 = Test2@2161fcdd

scala> y.foo(5)            
<console>:7: error: could not find implicit value for evidence parameter of type M[Int]
       y.foo(5)
            ^

scala> import Test2
     | ;
<console>:2: error: '.' expected but ';' found.
       ;
       ^

scala> import Test2._
import Test2._

scala> y.foo(5)        
class TestImplicits$$anon$1

scala> x.foo(5)        
class TestImplicits$$anon$1



I'm not sure exactly how to read the SLS spec, but I had assumed that the companion object of type T would be in the implicit scope...  See Relevant portion of SLS in section 7.2

The implicit scope of a type T consists of all companion modules (§5.4) of classes
that are associated with the implicit parameter’s type. Here, we say a class C is associated
with a type T , if it is a base class (§5.1.2) of some part of T . The parts of a type
T are:
• if T is a compound type T1 with . . . with Tn, the union of the parts of
T1, . . . , Tn, as well as T itself,
• if T is a parameterized type S[T1, . . . , Tn], the union of the parts of S and
T1, . . . , Tn,
• if T is a singleton type p.type, the parts of the type of p,
• if T is a type projection S#U, the parts of S as well as T itself,
• in all other cases, just T itself.


Reading this, it made me assume that perhaps the implicits need to be defined on T itself (rather than its companion...).  SO  I tried the following:

scala> class Test3 extends Test with TestImplicits
defined class Test3

scala> val z = new Test3                         
z: Test3 = Test3@4a5afcb1

scala> z.foo(5)
<console>:8: error: could not find implicit value for evidence parameter of type M[Int]
       z.foo(5)


As you can see, no dice.   Is there something obvious I'm missing, or should I file a bug?


Thanks!
- Josh Suereth

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland