From 6d2a838bb861c51ad7a82a0f6561d9dd063686fc Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 5 May 2016 12:47:28 +1000 Subject: [PATCH] Add impl restriction related to invokespecial to Java parents --- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 9 ++++++-- test/files/neg/trait-defaults-super.check | 4 ++++ test/files/neg/trait-defaults-super.scala | 21 +++++++++++++++++++ test/files/pos/trait-defaults-super.scala | 21 +++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 test/files/neg/trait-defaults-super.check create mode 100644 test/files/neg/trait-defaults-super.scala create mode 100644 test/files/pos/trait-defaults-super.scala diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 92aa75ef68f1..6cf23b063799 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1077,10 +1077,15 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { if (needsInterfaceCall(receiverClass)) bc.invokeinterface(receiverName, jname, mdescr, pos) else bc.invokevirtual (receiverName, jname, mdescr, pos) case Super => - if (receiverClass.isTraitOrInterface) { + if (receiverClass.isTrait && method.owner.isTrait && !method.owner.isJavaDefined) { val staticDesc = MethodBType(typeToBType(method.owner.info) :: method.info.paramTypes.map(typeToBType), typeToBType(method.info.resultType)).descriptor bc.invokestatic(receiverName, jname, staticDesc, pos) - } else bc.invokespecial (receiverName, jname, mdescr, pos) + } else { + if (receiverClass.isTraitOrInterface && !cnode.interfaces.contains(receiverName)) + reporter.error(pos, s"Implementation restriction: unable to emit a super call to ${receiverName}.${method.name} from ${cnode.name}. Add $receiverName as a direct parent of ${cnode.name}") + else + bc.invokespecial (receiverName, jname, mdescr, pos) + } } bmType.returnType diff --git a/test/files/neg/trait-defaults-super.check b/test/files/neg/trait-defaults-super.check new file mode 100644 index 000000000000..9868049bc542 --- /dev/null +++ b/test/files/neg/trait-defaults-super.check @@ -0,0 +1,4 @@ +trait-defaults-super.scala:14: error: Implementation restriction: unable to emit a super call to java/lang/Iterable.spliterator from C. Add java/lang/Iterable as a direct parent of C +class C extends T + ^ +one error found diff --git a/test/files/neg/trait-defaults-super.scala b/test/files/neg/trait-defaults-super.scala new file mode 100644 index 000000000000..def271e8e747 --- /dev/null +++ b/test/files/neg/trait-defaults-super.scala @@ -0,0 +1,21 @@ +trait T extends java.lang.Iterable[String] { + + override def spliterator(): java.util.Spliterator[String] = { + super[Iterable].spliterator + super.spliterator + null + } + def foo = { + super[Iterable].spliterator + super.spliterator + } + def iterator(): java.util.Iterator[String] = java.util.Collections.emptyList().iterator() +} +class C extends T +object Test { + def main(args: Array[String]): Unit = { + val t: T = new C + t.spliterator + t.foo + } +} diff --git a/test/files/pos/trait-defaults-super.scala b/test/files/pos/trait-defaults-super.scala new file mode 100644 index 000000000000..8f867ab5632d --- /dev/null +++ b/test/files/pos/trait-defaults-super.scala @@ -0,0 +1,21 @@ +trait T extends java.lang.Iterable[String] { + + override def spliterator(): java.util.Spliterator[String] = { + super[Iterable].spliterator + super.spliterator + null + } + def foo = { + super[Iterable].spliterator + super.spliterator + } + def iterator(): java.util.Iterator[String] = java.util.Collections.emptyList().iterator() +} +class C extends T with java.lang.Iterable[String] // super accessor is okay with Iterable as a direct parent +object Test { + def main(args: Array[String]): Unit = { + val t: T = new C + t.spliterator + t.foo + } +}