summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/runtime/JavaMirrors.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-08-03 18:28:03 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-03 18:37:15 +0200
commitce4bcb536279d97617f85da3f66b5296c6ee2b96 (patch)
treeeb4c866d243dbfae9f5bec6656f8913e5ed774bf /src/reflect/scala/reflect/runtime/JavaMirrors.scala
parent57fcda5cc5407b33d638f3c4d7c4f41a92fceac4 (diff)
downloadscala-ce4bcb536279d97617f85da3f66b5296c6ee2b96.tar.gz
scala-ce4bcb536279d97617f85da3f66b5296c6ee2b96.tar.bz2
scala-ce4bcb536279d97617f85da3f66b5296c6ee2b96.zip
SI-6175 reflect over classes with symbolic names
Top-level classes with symbolic names (having binary names like $colon$colon) have previously been incorrectly treated as local classes by Scala reflection. As a result they were loaded as if they weren't pickled (i.e. as Java classes). Moreover this bug also had a more subtle, but more dangerous manifestation. If such a class has already been loaded indirectly by unpickling another class (which refers to it in its pickle) and then someone tried to load it explicitly via classToScala, then it would be loaded twice (once as a Scala artifact and once as a Java artifact). This is a short route to ambiguities and crashes. The fix first checks whether a class with a suspicious name (having dollars) can be loaded as a Scala artifact (by looking it up in a symbol table). If this fails, the class is then loaded in Java style (as it was done before). Ambiguous names that can be interpreted both ways (e.g. foo_$colon$colon) are first resolved as Scala and then as Java. This prioritization cannot lead to errors, because Scala and Java artifacts with the same name cannot coexist, therefore loading a Scala artifact won't shadow a homonymous Java artifact.
Diffstat (limited to 'src/reflect/scala/reflect/runtime/JavaMirrors.scala')
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 64c47a5502..5eb7770de6 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -777,7 +777,16 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
lookupClass
else if (jclazz.isLocalClass0 || isInvalidClassName(jname))
// local classes and implementation classes not preserved by unpickling - treat as Java
- jclassAsScala(jclazz)
+ //
+ // upd. but only if they cannot be loaded as top-level classes
+ // otherwise we may mistake mangled symbolic names for mangled nested names
+ //
+ // in case when a Java binary name can be treated both as a top-level class and as a nested class
+ // (as described in http://groups.google.com/group/scala-internals/browse_thread/thread/10855403bbf04298)
+ // we check for a top-level class first
+ // this is totally correct, because a top-level class and a nested class with the same name cannot coexist
+ // so it's either one or another, but not both - therefore we always load $-bearing classes correctly
+ lookupClass orElse jclassAsScala(jclazz)
else if (jclazz.isArray)
ArrayClass
else