2

I'm trying to understand why implicit resolution (or perhaps type inference) fails for the following Scala code. In this code, compilation fails on the second to last line, but succeeds on a modified version of the line where types are explicitly provided.

object O {
  trait Wrapper[-A, +B] {
    def func: A => B
  }

  object Identity

  implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
    override def func: A => A = identity
  }

  // Compilation fails on the next line with error: 
  // found String("hello") 
  // required: A
  Identity.func("hello")
  // This line compiles.
  implicitly[Identity.type => Wrapper[String, String]].apply(Identity).func("hello")
}
emchristiansen
  • 3,550
  • 3
  • 26
  • 40
  • 3
    Not an answer, but at a glance it looks like you might be running into [this bug](https://issues.scala-lang.org/browse/SI-6472). See also my question [here](http://stackoverflow.com/q/13515169/334519), and [the issue I'd filed](https://issues.scala-lang.org/browse/SI-6776), which turned out to be (apparently) a duplicate of the one in my first link. – Travis Brown Jan 24 '13 at 00:17

2 Answers2

3

Travis Brown seems to be right, this is an occurence of the following: https://issues.scala-lang.org/browse/SI-6472

As a proof, I could make it compile using the work around given by Travis himself here: https://issues.scala-lang.org/browse/SI-6776

object O {
  trait Wrapper[-A, +B] {
    val funcFunc: A => B
    def func( arg: A ): B = funcFunc( arg )
  }

  private class Private
  trait BaseWrappable {
    // Dummy method (cannot ever be called, just a work around to help the compiler)
    def func( a: Private ) = ???
  }

  object Identity extends BaseWrappable

  implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
    val funcFunc: A => A = identity
  }

  Identity.func("hello")
}
Régis Jean-Gilles
  • 32,541
  • 5
  • 83
  • 97
  • As I wrote in my answer, there are more issues at play here. The result type of Identity.funcFunc is "A => A" which is a nonsense type (since there is no type A in scope). So there's obviously at least one bug in the compiler here. – Jesper Nordenberg Jan 24 '13 at 12:01
0

The code you have written is the same as:

class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
  override def func: A => A = identity
}

implicit def identityToIdentityWrapper[A](self: Identity.type) = new Identity2Wrapper[A](self)

Note that the type parameter A is unbound until the the result from the call to func is used. The Scala compiler is not smart enough to look that far ahead and determine the type of A. Also, you cannot create a value of type [A] A => A in Scala. I'm actually surprised that the compiler doesn't infer A to be of type Nothing like it does when you call identityToIdentityWrapper explicitly.

Jesper Nordenberg
  • 2,104
  • 11
  • 15
  • Jesper, the fact Travis' workaround works suggests to me the compiler _is_ supposed to "look that far ahead", but is just failing to due to a bug (as you mention in another comment). – emchristiansen Jan 24 '13 at 19:05