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

Why does implicit def conforms[T] return the subclass instance for implicit ev: Sub <:< Super?

1 reply
Cay Horstmann
Joined: 2009-09-04,
User offline. Last seen 42 years 45 weeks ago.

When I compile

import java.util._

object Main extends App {
println(implicitly[GregorianCalendar <:< Calendar])
}

with -Xprint:typer, I can see which evidence object I get. It is
scala.this.Predef.conforms[java.util.GregorianCalendar].

In Predef, we find these immortal lines:

sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
implicit def conforms[A]: A <:< A = new (A <:< A) { def apply(x: A) = x }

The way I understand it, one looks for an implicit GregorianCalendar
<:< Calendar instance. Or an instance of a subtype. Indeed,
conforms[GregorianCalendar] is such a subtype instance. But so is
conforms[Calendar], as the REPL confirms:

val ev1: GregorianCalendar <:< Calendar = conforms[GregorianCalendar]
ev1: <:<[java.util.GregorianCalendar,java.util.Calendar] =
val ev2: GregorianCalendar <:< Calendar = conforms[Calendar]
ev2: <:<[java.util.GregorianCalendar,java.util.Calendar] =

Why isn't this ambiguous?

Thanks,

Cay

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Why does implicit def conforms[T] return the subclass insta

On Thu, Aug 11, 2011 at 3:38 AM, Cay Horstmann wrote:
> When I compile
>
> import java.util._
>
> object Main extends App {
>  println(implicitly[GregorianCalendar <:< Calendar])
> }
>
> with -Xprint:typer, I can see which evidence object I get. It is
> scala.this.Predef.conforms[java.util.GregorianCalendar].
>
> In Predef, we find these immortal lines:
>
> sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
> implicit def conforms[A]: A <:< A = new (A <:< A) { def apply(x: A) = x }
>
> The way I understand it, one looks for an implicit GregorianCalendar
> <:< Calendar instance. Or an instance of a subtype. Indeed,
> conforms[GregorianCalendar] is such a subtype instance. But so is
> conforms[Calendar], as the REPL confirms:
>
> val ev1: GregorianCalendar <:< Calendar = conforms[GregorianCalendar]
> ev1: <:<[java.util.GregorianCalendar,java.util.Calendar] =
> val ev2: GregorianCalendar <:< Calendar = conforms[Calendar]
> ev2: <:<[java.util.GregorianCalendar,java.util.Calendar] =
>
> Why isn't this ambiguous?

An implicit method can't be ambiguous with itself. Type inference
selects the most specific type argument.

scala> class A; class B extends A
defined class A
defined class B

scala> conforms[A]: (B => A)
res1: B => A =

scala> conforms[B]: (B => A)
res2: B => A =

scala> conforms: (B => A)
res3: B => A =

// (scala.this.Predef.conforms[B]

For more details, see the section Local Type Inference in the SLS.

-jason

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