From 617706644139d5731b10b3c77c647e3b70aa07b3 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 10 Jun 2012 23:38:39 +0200 Subject: SI-5162 Exclude super.foo from the erasure cast of SI-4283 If the target method is defined in Java, treat the super reference as an error, otherwise allow it in the knowledge that Scala loosens the access restrictions on its generated classes. Moves the test for that bug out of pending-ville. It's sufficient to place Test in the empty package to exercise the right code paths. --- .../scala/tools/nsc/transform/Erasure.scala | 27 ++++++++++++++-------- test/files/neg/t4283b.check | 4 ++++ test/files/neg/t4283b/AbstractFoo.java | 5 ++++ test/files/neg/t4283b/ScalaBipp.scala | 5 ++++ test/files/neg/t4283b/Test.scala | 3 +++ test/files/run/t4283.check | 5 ++++ test/files/run/t4283/AbstractFoo.java | 6 +++++ test/files/run/t4283/ScalaBipp.scala | 5 ++++ test/files/run/t4283/Test.scala | 16 +++++++++++++ test/files/run/t5162.scala | 19 +++++++++++++++ test/pending/run/t4283/AbstractFoo.java | 6 ----- test/pending/run/t4283/IllegalAccess.scala | 17 -------------- test/pending/run/t4283/ScalaBipp.scala | 5 ---- 13 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 test/files/neg/t4283b.check create mode 100644 test/files/neg/t4283b/AbstractFoo.java create mode 100644 test/files/neg/t4283b/ScalaBipp.scala create mode 100644 test/files/neg/t4283b/Test.scala create mode 100644 test/files/run/t4283.check create mode 100644 test/files/run/t4283/AbstractFoo.java create mode 100644 test/files/run/t4283/ScalaBipp.scala create mode 100644 test/files/run/t4283/Test.scala create mode 100644 test/files/run/t5162.scala delete mode 100644 test/pending/run/t4283/AbstractFoo.java delete mode 100644 test/pending/run/t4283/IllegalAccess.scala delete mode 100644 test/pending/run/t4283/ScalaBipp.scala diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ce16facf77..1276d62995 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1042,18 +1042,27 @@ abstract class Erasure extends AddInterfaces assert(overridden != NoSymbol, tree.symbol) tree.symbol = overridden } + def isAccessible(sym: Symbol) = localTyper.context.isAccessible(sym, sym.owner.thisType) if (!isAccessible(owner) && qual.tpe != null) { - // Todo: Figure out how qual.tpe could be null in the check above (it does appear in build where SwingWorker.this - // has a null type). - val qualSym = qual.tpe.widen.typeSymbol - if (isAccessible(qualSym) && !qualSym.isPackageClass && !qualSym.isPackageObjectClass) { - // insert cast to prevent illegal access error (see #4283) - // util.trace("insert erasure cast ") (*/ - treeCopy.Select(tree, gen.mkAttributedCast(qual, qual.tpe.widen), name) //) - } else tree + qual match { + case Super(_, _) => + // Insert a cast here at your peril -- see SI-5162. Bail out if the target method is defined in + // Java, otherwise, we'd get an IllegalAccessError at runtime. If the target method is defined in + // Scala, however, we should have access. + if (owner.isJavaDefined) unit.error(tree.pos, s"Unable to access ${tree.symbol.fullLocationString} with a super reference.") + tree + case _ => + // Todo: Figure out how qual.tpe could be null in the check above (it does appear in build where SwingWorker.this + // has a null type). + val qualSym = qual.tpe.widen.typeSymbol + if (isAccessible(qualSym) && !qualSym.isPackageClass && !qualSym.isPackageObjectClass) { + // insert cast to prevent illegal access error (see #4283) + // util.trace("insert erasure cast ") (*/ + treeCopy.Select(tree, gen.mkAttributedCast(qual, qual.tpe.widen), name) //) + } else tree + } } else tree - case Template(parents, self, body) => assert(!currentOwner.isImplClass) //Console.println("checking no dble defs " + tree)//DEBUG diff --git a/test/files/neg/t4283b.check b/test/files/neg/t4283b.check new file mode 100644 index 0000000000..30d03a310d --- /dev/null +++ b/test/files/neg/t4283b.check @@ -0,0 +1,4 @@ +Test.scala:2: error: Unable to access method f in class AbstractFoo with a super reference. + override def f(): Int = super.f() + ^ +one error found diff --git a/test/files/neg/t4283b/AbstractFoo.java b/test/files/neg/t4283b/AbstractFoo.java new file mode 100644 index 0000000000..7abcd5e76b --- /dev/null +++ b/test/files/neg/t4283b/AbstractFoo.java @@ -0,0 +1,5 @@ +package test; + +/* package private */ class AbstractFoo { + public int f() { return 2; } +} diff --git a/test/files/neg/t4283b/ScalaBipp.scala b/test/files/neg/t4283b/ScalaBipp.scala new file mode 100644 index 0000000000..36dea9f4de --- /dev/null +++ b/test/files/neg/t4283b/ScalaBipp.scala @@ -0,0 +1,5 @@ +package test + +class ScalaBipp extends AbstractFoo { + def make: Option[ScalaBipp] = Option(this) +} diff --git a/test/files/neg/t4283b/Test.scala b/test/files/neg/t4283b/Test.scala new file mode 100644 index 0000000000..0dc5636ff8 --- /dev/null +++ b/test/files/neg/t4283b/Test.scala @@ -0,0 +1,3 @@ +object Derived extends test.ScalaBipp { + override def f(): Int = super.f() +} diff --git a/test/files/run/t4283.check b/test/files/run/t4283.check new file mode 100644 index 0000000000..0d27989761 --- /dev/null +++ b/test/files/run/t4283.check @@ -0,0 +1,5 @@ +2 +2 +1 +1 +1 diff --git a/test/files/run/t4283/AbstractFoo.java b/test/files/run/t4283/AbstractFoo.java new file mode 100644 index 0000000000..0403271b74 --- /dev/null +++ b/test/files/run/t4283/AbstractFoo.java @@ -0,0 +1,6 @@ +package test; + +/* package private */ class AbstractFoo { + public int t = 1; + public int f() { return 2; } +} \ No newline at end of file diff --git a/test/files/run/t4283/ScalaBipp.scala b/test/files/run/t4283/ScalaBipp.scala new file mode 100644 index 0000000000..36dea9f4de --- /dev/null +++ b/test/files/run/t4283/ScalaBipp.scala @@ -0,0 +1,5 @@ +package test + +class ScalaBipp extends AbstractFoo { + def make: Option[ScalaBipp] = Option(this) +} diff --git a/test/files/run/t4283/Test.scala b/test/files/run/t4283/Test.scala new file mode 100644 index 0000000000..af72fa62f9 --- /dev/null +++ b/test/files/run/t4283/Test.scala @@ -0,0 +1,16 @@ +object Test { + + def main(args: Array[String]) { + val x = (new test.ScalaBipp).make.get.asInstanceOf[test.ScalaBipp].f() + println(x) + val y = (new test.ScalaBipp).make.get.f() + println(y) + val u = (new test.ScalaBipp).make.get.asInstanceOf[test.ScalaBipp].t + println(u) + val v = (new test.ScalaBipp).make.get.t + println(v) + val sb: test.ScalaBipp = (new test.ScalaBipp).make.get + val z = sb.t + println(z) + } +} diff --git a/test/files/run/t5162.scala b/test/files/run/t5162.scala new file mode 100644 index 0000000000..4f91932b6e --- /dev/null +++ b/test/files/run/t5162.scala @@ -0,0 +1,19 @@ +// In run, rather than pos, to check for problems like SI-4283 +object O1 { + private[O1] class Base { + def foo: Int = 0 + } + class Mediator extends Base +} + +object O2 { + class Derived extends O1.Mediator { + override def foo: Int = super.foo + } +} + +object Test { + def main(args: Array[String]) { + new O2.Derived().foo + } +} diff --git a/test/pending/run/t4283/AbstractFoo.java b/test/pending/run/t4283/AbstractFoo.java deleted file mode 100644 index 0403271b74..0000000000 --- a/test/pending/run/t4283/AbstractFoo.java +++ /dev/null @@ -1,6 +0,0 @@ -package test; - -/* package private */ class AbstractFoo { - public int t = 1; - public int f() { return 2; } -} \ No newline at end of file diff --git a/test/pending/run/t4283/IllegalAccess.scala b/test/pending/run/t4283/IllegalAccess.scala deleted file mode 100644 index 33039c9350..0000000000 --- a/test/pending/run/t4283/IllegalAccess.scala +++ /dev/null @@ -1,17 +0,0 @@ -package other - -object IllegalAccess { - def main(args: Array[String]) { - val x = (new test.ScalaBipp).make.get.asInstanceOf[test.ScalaBipp].f() - println(x) - val y = (new test.ScalaBipp).make.get.f() - println(y) - val u = (new test.ScalaBipp).make.get.asInstanceOf[test.ScalaBipp].t - println(u) - val v = (new test.ScalaBipp).make.get.t - println(v) - val sb: test.ScalaBipp = (new test.ScalaBipp).make.get - val z = sb.t - println(z) - } -} diff --git a/test/pending/run/t4283/ScalaBipp.scala b/test/pending/run/t4283/ScalaBipp.scala deleted file mode 100644 index 36dea9f4de..0000000000 --- a/test/pending/run/t4283/ScalaBipp.scala +++ /dev/null @@ -1,5 +0,0 @@ -package test - -class ScalaBipp extends AbstractFoo { - def make: Option[ScalaBipp] = Option(this) -} -- cgit v1.2.3