Skip to content

Commit

Permalink
Fix scala#1284: Make classTag depend directly on erasure
Browse files Browse the repository at this point in the history
In the end, a classTag reflects the erased version of a type. The only
condition for its generation should be that the erasure is stable under
possible instantiations.
  • Loading branch information
odersky committed Jul 25, 2016
1 parent 11f06fe commit 15fb8e1
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
18 changes: 18 additions & 0 deletions src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ object TypeErasure {
else tp1
}
}

/** Does the (possibly generic) type `tp` have the same erasure in all its
* possible instantiations?
*/
def hasStableErasure(tp: Type)(implicit ctx: Context): Boolean = tp match {
case tp: TypeRef =>
tp.info match {
case TypeAlias(alias) => hasStableErasure(alias)
case _: ClassInfo => true
case _ => false
}
case tp: PolyParam => false
case tp: TypeProxy => hasStableErasure(tp.superType)
case tp: AndOrType => hasStableErasure(tp.tp1) && hasStableErasure(tp.tp2)
case _ => false
}
}
import TypeErasure._

Expand Down Expand Up @@ -493,4 +509,6 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
println(s"no sig for $tp")
throw ex
}


}
16 changes: 7 additions & 9 deletions src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import printing.Showable
import Contexts._
import Types._
import Flags._
import TypeErasure.{erasure, hasStableErasure}
import Mode.ImplicitsEnabled
import Denotations._
import NameOps._
Expand Down Expand Up @@ -479,15 +480,12 @@ trait Implicits { self: Typer =>
formal.argTypes match {
case arg :: Nil =>
val tp = fullyDefinedType(arg, "ClassTag argument", pos)
tp.underlyingClassRef(refinementOK = false) match {
case tref: TypeRef =>
return ref(defn.ClassTagModule)
.select(nme.apply)
.appliedToType(tp)
.appliedTo(clsOf(tref))
.withPos(pos)
case _ =>
}
if (hasStableErasure(tp))
return ref(defn.ClassTagModule)
.select(nme.apply)
.appliedToType(tp)
.appliedTo(clsOf(erasure(tp)))
.withPos(pos)
case _ =>
}
EmptyTree
Expand Down
8 changes: 8 additions & 0 deletions tests/run/i1284.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
case object A
case object B

object Test {
def main(args: Array[String]): Unit = {
assert(Array(A, B).deep.toString == "Array(A, B)")
}
}

0 comments on commit 15fb8e1

Please sign in to comment.