1

I've defined an implicit class providing a method foo on all instances of Double. Strangely, this method can now also be called e.g. on Float instances, which is shown by the following example accepted by scalac 2.12.5 (use -Xscript Foo):

implicit class DoubleOps(value: Double) {
  def foo: Double = value
}

val x: Float = 1f
val y = x.foo

If I try to do the same with my own types, replacing Float and Double with MyFloat and MyDouble respectively, foo is not available on MyFloat instances.

trait MyDouble

object MyDouble {
  implicit class MyFloatAsMyDouble(value: MyFloat) extends MyDouble
}

trait MyFloat

implicit class MyDoubleOps(value: MyDouble) {
  def foo: MyDouble = value
}

val x: MyFloat = new MyFloat { }
val y = x.foo

$ scalac -Xscript Foo foo.scala
foo.scala:14: error: value foo is not a member of this.MyFloat
val y = x.foo
          ^
one error found

This is in line with my understand of how the compiler uses implicits to search for members not found on a type directly. But why does the first example still work?

Feuermurmel
  • 9,490
  • 10
  • 60
  • 90

1 Answers1

5

I believe this is a case of numeric widening achieved through weak conformance. (There is an active proposal to drop this from the language.)

jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Thanks! Those references are interesting. I can see how this applies to my observation. Dotty seems to have a [much more restricted](http://dotty.epfl.ch/docs/reference/dropped-features/weak-conformance-spec.html) approach to numeric widening, probably resulting in less surprises. – Feuermurmel Feb 20 '19 at 13:31