summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala13
-rw-r--r--test/files/run/spec-t3896.check2
-rw-r--r--test/files/run/spec-t3896.scala18
3 files changed, 30 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 5f4a90b84b..387f069875 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -416,6 +416,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def enterMember(sym: Symbol): Symbol = {
typeEnv(sym) = fullEnv ++ typeEnv(sym) // append the full environment
sym.setInfo(sym.info.substThis(clazz, ThisType(cls)).subst(oldClassTParams, newClassTParams map (_.tpe)))
+
+ // we remove any default parameters. At this point, they have been all
+ // resolved by the type checker. Later on, erasure re-typechecks everything and
+ // chokes if it finds default parameters for specialized members, even though
+ // they are never needed.
+ sym.info.paramss.flatten foreach (_.resetFlag(DEFAULTPARAM))
+
decls1.enter(subst(fullEnv)(sym))
}
@@ -1052,7 +1059,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
log("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s"
.format(tree, symbol.tpe, tree.tpe, env, specializedName(symbol, env)))
if (!env.isEmpty) { // a method?
- val specMember = qual.tpe.member(specializedName(symbol, env))
+ val specMember = qual.tpe.member(specializedName(symbol, env)) suchThat (_.tpe =:= qual.tpe)
if (specMember ne NoSymbol)
if (typeEnv(specMember) == env) Some(specMember)
else {
@@ -1135,8 +1142,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} else overloads(symbol).find(_.sym.info =:= symbol.info) match {
case Some(specMember) =>
val qual1 = transform(qual)
- if (settings.debug.value) log("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym.name))
- localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym.name)))
+ if (settings.debug.value) log("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym))
+ localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym)))
case None =>
super.transform(tree)
}
diff --git a/test/files/run/spec-t3896.check b/test/files/run/spec-t3896.check
new file mode 100644
index 0000000000..bb101b641b
--- /dev/null
+++ b/test/files/run/spec-t3896.check
@@ -0,0 +1,2 @@
+true
+true
diff --git a/test/files/run/spec-t3896.scala b/test/files/run/spec-t3896.scala
new file mode 100644
index 0000000000..4c4dadbe13
--- /dev/null
+++ b/test/files/run/spec-t3896.scala
@@ -0,0 +1,18 @@
+// see ticket #3896. Tests interaction between overloading, specialization and default params
+trait Atomic[@specialized(Boolean) T] {
+ def x: T
+
+ // crash depends on the overloading: if second method is "g", no crash.
+ def f(fn: T => T): Boolean = f(fn(x))
+ def f[R](a: T, b: R = true) = b
+}
+class AtomicBoolean(val x: Boolean) extends Atomic[Boolean]
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val e = new AtomicBoolean(false)
+ val x = e.f( (a : Boolean) => !a ) // ok
+ println( e.f( (a : Boolean) => !a ) toString ) // ok
+ println( e.f( (a : Boolean) => !a) ) // compiler crash
+ }
+}