summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-04-13 15:07:21 +0000
committerMartin Odersky <odersky@gmail.com>2011-04-13 15:07:21 +0000
commit514d01c1ce9219a10f37d50a39cfeb420d76e38c (patch)
treef63d82982a4973ab8117b7dcc0730b3723a8264f
parent703bbdae73800e49d737e133e3a05929005294fc (diff)
downloadscala-514d01c1ce9219a10f37d50a39cfeb420d76e38c.tar.gz
scala-514d01c1ce9219a10f37d50a39cfeb420d76e38c.tar.bz2
scala-514d01c1ce9219a10f37d50a39cfeb420d76e38c.zip
Fixes my part of #4283 by inserting another cas...
Fixes my part of #4283 by inserting another cast pre-emptively when an IllegalAccess error is possible in an erasure-inserted cast. Review by extempore.
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--test/pending/run/t4283/AbstractFoo.java3
-rw-r--r--test/pending/run/t4283/IllegalAccess.scala14
5 files changed, 37 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index f9f2f94917..36552894e5 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -13,6 +13,7 @@ import Flags._
abstract class Erasure extends AddInterfaces
with typechecker.Analyzer
+ with TypingTransformers
with ast.TreeDSL
{
import global._
@@ -922,9 +923,12 @@ abstract class Erasure extends AddInterfaces
* - Add bridge definitions to a template.
* - Replace all types in type nodes and the EmptyTree object by their erasure.
* Type nodes of type Unit representing result types of methods are left alone.
+ * - Given a selection q.s, where the owner of `s` is not accessible but the
+ * type symbol of q's type qT is accessible, insert a cast (q.asInstanceOf[qT]).s
+ * This prevents illegal access errors (see #4283).
* - Reset all other type attributes to null, thus enforcing a retyping.
*/
- private val preTransformer = new Transformer {
+ private val preTransformer = new TypingTransformer(unit) {
def preErase(tree: Tree): Tree = tree match {
case ClassDef(mods, name, tparams, impl) =>
if (settings.debug.value)
@@ -1042,14 +1046,25 @@ abstract class Erasure extends AddInterfaces
}
}
- case Select(_, _) =>
+ case Select(qual, name) =>
+ val owner = tree.symbol.owner
// println("preXform: "+ (tree, tree.symbol, tree.symbol.owner, tree.symbol.owner.isRefinementClass))
- if (tree.symbol.owner.isRefinementClass) {
+ if (owner.isRefinementClass) {
val overridden = tree.symbol.allOverriddenSymbols
assert(!overridden.isEmpty, tree.symbol)
tree.symbol = overridden.head
}
- tree
+ 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, qual AS_ATTR qual.tpe.widen, name) //)
+ } else tree
+ } else tree
case Template(parents, self, body) =>
assert(!currentOwner.isImplClass)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index eb9eb9dbec..7567cf6483 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -383,7 +383,7 @@ trait Contexts { self: Analyzer =>
* @param superAccess ...
* @return ...
*/
- def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean): Boolean = {
+ def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean = false): Boolean = {
lastAccessCheckDetails = ""
// Console.println("isAccessible(%s, %s, %s)".format(sym, pre, superAccess))
@@ -507,7 +507,7 @@ trait Contexts { self: Analyzer =>
*/
private def isQualifyingImplicit(sym: Symbol, pre: Type, imported: Boolean) =
sym.isImplicit &&
- isAccessible(sym, pre, false) &&
+ isAccessible(sym, pre) &&
!(imported && {
val e = scope.lookupEntry(sym.name)
(e ne null) && (e.owner == scope)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 09786a4aae..5d6796b41a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -183,7 +183,7 @@ trait Typers extends Modes {
namerCache
}
- private[typechecker] var context = context0
+ var context = context0
def context1 = context
/** Check that <code>tree</code> is a stable expression.
diff --git a/test/pending/run/t4283/AbstractFoo.java b/test/pending/run/t4283/AbstractFoo.java
index 6d4e8f4e22..0403271b74 100644
--- a/test/pending/run/t4283/AbstractFoo.java
+++ b/test/pending/run/t4283/AbstractFoo.java
@@ -1,5 +1,6 @@
package test;
/* package private */ class AbstractFoo {
- public int t;
+ 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
index e1bce15cf8..12de7e4649 100644
--- a/test/pending/run/t4283/IllegalAccess.scala
+++ b/test/pending/run/t4283/IllegalAccess.scala
@@ -1,5 +1,17 @@
package other
object IllegalAccess {
- val x = (new test.ScalaBipp).make.get.t // java.lang.IllegalAccessError: tried to access class test.AbstractFoo from class other.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)
+ }
}