From 09bf95675b06a0912ab1e3c8cdcab9a19eca48d4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 2 Jun 2012 13:24:00 +0200 Subject: SI-5167 An impl class method should refer to its own parameter symbols. Rather than those of the original method in the trait. If they are shared, parameter renaming in the implementaion class is visible in the original method. This led to a crash in the resident compiler when looking up the default argument getter. --- .../scala/tools/nsc/transform/AddInterfaces.scala | 20 +++++++++++++++----- test/files/res/t5167.check | 4 ++++ test/files/res/t5167.res | 2 ++ test/files/res/t5167/t5167_1.scala | 12 ++++++++++++ test/files/res/t5167/t5167_2.scala | 7 +++++++ 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 test/files/res/t5167.check create mode 100644 test/files/res/t5167.res create mode 100644 test/files/res/t5167/t5167_1.scala create mode 100644 test/files/res/t5167/t5167_2.scala diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index e5fc98f23c..8c5d25e6c4 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -257,11 +257,21 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => /** Transforms the member tree containing the implementation * into a member of the impl class. */ - private def implMethodDef(tree: Tree): Tree = ( - implMethodMap get tree.symbol - map (impl => new ChangeOwnerAndReturnTraverser(tree.symbol, impl)(tree setSymbol impl)) - getOrElse abort("implMethod missing for " + tree.symbol) - ) + private def implMethodDef(tree: Tree): Tree = { + val impl = implMethodMap.getOrElse(tree.symbol, abort("implMethod missing for " + tree.symbol)) + + val newTree = if (impl.isErroneous) tree else { // e.g. res/t687 + // SI-5167: Ensure that the tree that we are grafting refers the parameter symbols from the + // new method symbol `impl`, rather than the symbols of the original method signature in + // the trait. `tree setSymbol impl` does *not* suffice! + val DefDef(_, _, _, vparamss, _, _) = tree + val oldSyms = vparamss.flatten.map(_.symbol) + val newSyms = impl.info.paramss.flatten + assert(oldSyms.length == newSyms.length, (oldSyms, impl, impl.info)) + tree.substTreeSyms(oldSyms, newSyms) + } + new ChangeOwnerAndReturnTraverser(newTree.symbol, impl)(newTree setSymbol impl) + } /** Add mixin constructor definition * def $init$(): Unit = () diff --git a/test/files/res/t5167.check b/test/files/res/t5167.check new file mode 100644 index 0000000000..6cf64f734b --- /dev/null +++ b/test/files/res/t5167.check @@ -0,0 +1,4 @@ + +nsc> +nsc> +nsc> diff --git a/test/files/res/t5167.res b/test/files/res/t5167.res new file mode 100644 index 0000000000..a485cbee41 --- /dev/null +++ b/test/files/res/t5167.res @@ -0,0 +1,2 @@ +t5167/t5167_1.scala +t5167/t5167_2.scala \ No newline at end of file diff --git a/test/files/res/t5167/t5167_1.scala b/test/files/res/t5167/t5167_1.scala new file mode 100644 index 0000000000..ed28243507 --- /dev/null +++ b/test/files/res/t5167/t5167_1.scala @@ -0,0 +1,12 @@ +package compilerbug + +trait SadTrait { + def buggyMethod[T](argWithDefault1: Int = 0)(argWithDefault2: String = "default") { + for (i <- 0 to 1) { + val x = argWithDefault1 + val y = argWithDefault2 + } + } +} + +object SadObject extends SadTrait diff --git a/test/files/res/t5167/t5167_2.scala b/test/files/res/t5167/t5167_2.scala new file mode 100644 index 0000000000..5aa56efe75 --- /dev/null +++ b/test/files/res/t5167/t5167_2.scala @@ -0,0 +1,7 @@ +package compilerbug + +class TestClass { + def repro() { + SadObject.buggyMethod[Int]()() + } +} -- cgit v1.2.3