trait Elems {
class Elem[A] extends Dummy
val UnitElement: Elem[Unit]
// Workaround 1: if you use an object rather than a val, the typechecker
// uses GADT refinement to adapt the patten type of `a.Elem[Unit]` to
// `a.Elem[$1]`. See `inferModulePattern`, which calls `instantiateTypeParams`.
//
// object UnitElement extends Elem[Unit]
// Workaround 2: Define `Dummy` at the top level, rather than
// as a member of `Elems`. Even without GADT refinement, the
// check for `isPopulated(BadMatch.this.a.Elem[Unit], ?#Elem[?]`)
// seems to be happy that there is a value that inhabits both
// types.
//
// I think thie problem here is that `?#Elem[?]`.baseType(DummyClass)
// returns `Elems.this.Dummy`, rather than `?#Dummy`. (? is the
// Wildcard type).
//
// We should update `AsSeenFromMap` as follows to fix this:
//
// diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
// index af51281..316db7a 100644
// --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
// +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
// @@ -616,3 +616,3 @@ private[internal] trait TypeMaps {
// private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) =
// - (clazz == candidate) && (pre.widen.typeSymbol isSubClass clazz)
// + (clazz == candidate) && ((pre.widen.typeSymbol isSubClass clazz) || (pre eq WildcardType))
trait Dummy
}
class BadMatch[A <: Elems](a: A) {
def toLuaValue(eX: a.Elem[_]): String = eX match {
case a.UnitElement => "" // type mismatch
}
}
Minimal example at https://gist.github.com/retronym/41084b66d1df9904558d63797c579a2c, thanks to Jason Zaugg: