Skip to content

Fix #1284: Make classTag depend directly on erasure #1412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these newlines?

}
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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call was previously returning NoType on some refined types. I'm not sure whether the new logic returns false on them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not directly comparable. My point is the new implementation has some justification (stable erasure) where the old one hadn't.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

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)))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an interesting DSL! Does it cover the entire language, or it just contains a few most used utilities?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It covers about 30 ops, maybe half of them construct syntax trees. See ast.tpd#TreeOps for where it is defined.

.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)")
}
}