3

The compiler is able to provide evidence about type parameters, e.g:

def foo[A, B](implicit ev: A <:< B): B

A look at the type definition for <:< in Predef shows

sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
  1. Can anyone explain the implicit resolution chain here? How can $conforms[A]: A <:< A convince the compiler to create an instance of <:<[List[String], Seq[String]] for instance? Or <:<[Dog, Animal]. And what happens if (when) the .asInstanceOf call throws an exception?
  2. Why is the subclassing of => necessary?
gogstad
  • 3,607
  • 1
  • 29
  • 32

1 Answers1

1

You can see it in the scala.Predef object: https://github.com/scala-native/scala-native/blob/master/scalalib/overrides-2.11/scala/Predef.scala#L372

@implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable

private[this] lazy val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
@inline implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

@deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
def conforms[A]: A <:< A = $conforms[A]

<:<[-From, +To] contravariant over Form and covariant over To, hence <:<[Seq[String], Seq[String]] is a subtype of <:<[List[String], Seq[String]] (because List[String] is a subtype of Seq[String] and -From is contravariant). So, when you write implicit ev List[String] <:< Seq[String] the compiler use <:<[Seq[String], Seq[String]]

When you write implicit ev T <:< D and there is no A that conforms T <: A <: D, the compiler doesn't compile it, because there is no <:<[A, A] that conforms <:<[A, A] <: <:<[T, D]. So, .asInstanceOf never throws an exception inside $conforms in runtime.

Also, a very good blog post about it: http://blog.bruchez.name/2015/11/generalized-type-constraints-in-scala.html

Aleksey Isachenkov
  • 1,230
  • 6
  • 16