From e5e691ea2dd53abb64306b91bf172aaa8e2e6b9c Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 11 Mar 2017 16:19:31 +0100 Subject: Fix overriding a Java method with varargs If A method like: override def foo(x: Object*) overrides a Java method, it needs to be rewritten as: def foo(x: Seq[Object]) override def foo(x: Array[Object]): Object = foo(Predef.wrapRefArray(x)) This should be handled by ElimRepeated but there were two bugs: - `addVarArgsBridge` was called at phase `thisTransformer.next`, this is too late to create the bridge since `T*` has already been rewritten as `Seq[T]` - The original method symbol needs to have the `override` flag dropped, since it doesn't override anything. Furthermore, RefChecks had to be moved after ElimRepeated, otherwise the testcase would fail the overriding checks. --- compiler/src/dotty/tools/dotc/Compiler.scala | 4 ++-- compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala | 9 +++++++-- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 3 +++ 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'compiler') diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 1d319242b..f413fc902 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -48,9 +48,9 @@ class Compiler { List(new Pickler), // Generate TASTY info List(new FirstTransform, // Some transformations to put trees into a canonical form new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars - List(new RefChecks, // Various checks mostly related to abstract members and overriding - new CheckStatic, // Check restrictions that apply to @static members + List(new CheckStatic, // Check restrictions that apply to @static members new ElimRepeated, // Rewrite vararg parameters and arguments + new RefChecks, // Various checks mostly related to abstract members and overriding new NormalizeFlags, // Rewrite some definition flags new ExtensionMethods, // Expand methods of value classes with extension methods new ExpandSAMs, // Expand single abstract method closures to anonymous classes diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index 258b7f234..e67b3f114 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -95,8 +95,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati assert(ctx.phase == thisTransformer) def overridesJava = tree.symbol.allOverriddenSymbols.exists(_ is JavaDefined) if (tree.symbol.info.isVarArgsMethod && overridesJava) - addVarArgsBridge(tree)(ctx.withPhase(thisTransformer.next)) - else + addVarArgsBridge(tree) + else tree } @@ -120,6 +120,11 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati .appliedToArgs(vrefs :+ TreeGen.wrapArray(varArgRef, elemtp)) .appliedToArgss(vrefss1) }) + + // Drop the override flag on the user-written method, only the added bridge + // is a real override. + original.copySymDenotation(initFlags = original.flags &~ Override).installAfter(thisTransformer) + Thicket(ddef, bridgeDef) } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 23d05e087..e8ff7d572 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -766,6 +766,9 @@ class RefChecks extends MiniPhase { thisTransformer => override def phaseName: String = "refchecks" + // Needs to run after ElimRepeated for override checks involving varargs methods + override def runsAfter = Set(classOf[ElimRepeated]) + val treeTransform = new Transform(NoLevelInfo) class Transform(currentLevel: RefChecks.OptLevelInfo = RefChecks.NoLevelInfo) extends TreeTransform { -- cgit v1.2.3