Skip to content

Instantly share code, notes, and snippets.

@retronym
Last active December 29, 2015 17:29
Show Gist options
  • Save retronym/7704153 to your computer and use it in GitHub Desktop.
Save retronym/7704153 to your computer and use it in GitHub Desktop.
Unraveling case class pattern matching soundness
scala> trait Contra[-A] { def accept(p: A): Unit }
defined trait Contra
scala> trait T; case class Unravel[A](m: Contra[A], msg: A) extends T
defined trait T
defined class Unravel
scala> val us = Unravel[String](new Contra[String] { def accept(x: String) = x.length }, "")
us: Unravel[String] = Unravel($anon$1@69e8c998,)
scala> us match { case Unravel(m, _) => m.accept(0) }
<console>:13: error: type mismatch;
found : Int(0)
required: String
us match { case Unravel(m, _) => m.accept(0) }
scala> (us: T) match { case Unravel(m, _) => m.accept(0) }
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at $anon$1.accept(<console>:11)
... 32 elided
scala> Unravel.unapply[Any](us.asInstanceOf[Unravel[Any]]).get._1.accept(0)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at $anon$1.accept(<console>:11)
... 32 elided
scala> Unravel.unapply[Any](us)
<console>:13: error: type mismatch;
found : Unravel[String]
required: Unravel[Any]
Note: String <: Any, but class Unravel is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
Unravel.unapply[Any](us)
^
scala> Unravel.unapply(us)
res12: Option[(Contra[String], String)] = Some(($anon$1@69e8c998,))
scala> Unravel.unapply(us: Unravel[_])
warning: there were 1 feature warning(s); re-run with -feature for details
res13: Option[(Contra[_$1], _$1)] forSome { type _$1 } = Some(($anon$1@69e8c998,))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment