diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 13 | ||||
-rw-r--r-- | test/files/run/spec-t3896.check | 2 | ||||
-rw-r--r-- | test/files/run/spec-t3896.scala | 18 |
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 + } +} |