Skip to content

Fix overriding a Java method with varargs #2076

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 2 commits into from
Mar 12, 2017
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
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 17 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,21 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
elimRepeated(tp)


override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation =
super.transform(ref) match {
case ref1: SymDenotation if (ref1 ne ref) && overridesJava(ref1.symbol) =>
// This method won't override the corresponding Java method at the end of this phase,
// only the bridge added by `addVarArgsBridge` will.
ref1.copySymDenotation(initFlags = ref1.flags &~ Override)
case ref1 =>
ref1
}

override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym is Method

private def overridesJava(sym: Symbol)(implicit ctx: Context) = sym.allOverriddenSymbols.exists(_ is JavaDefined)

private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match {
case tp @ MethodType(paramNames, paramTypes) =>
val resultType1 = elimRepeated(tp.resultType)
Expand Down Expand Up @@ -93,10 +106,9 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
*/
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
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
if (tree.symbol.info.isVarArgsMethod && overridesJava(tree.symbol))
addVarArgsBridge(tree)
else
tree
}

Expand All @@ -120,6 +132,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
.appliedToArgs(vrefs :+ TreeGen.wrapArray(varArgRef, elemtp))
.appliedToArgss(vrefss1)
})

Thicket(ddef, bridgeDef)
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions tests/pos-java-interop/varargsOverride/Base.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Base {
public Object foo(Object... x) {
return x;
}
}
3 changes: 3 additions & 0 deletions tests/pos-java-interop/varargsOverride/Sub.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Sub extends Base {
override def foo(x: Object*): Object = x
}