summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-03-25 15:50:41 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-03-25 15:58:32 +0100
commitedee27f59f17873b378d96504d0b20013a31d081 (patch)
treea87c8a5d5050c9f128381f86346856a0a0a85a66
parent1187c9896c097e6e591e5655b35f52c06b3c900a (diff)
downloadscala-edee27f59f17873b378d96504d0b20013a31d081.tar.gz
scala-edee27f59f17873b378d96504d0b20013a31d081.tar.bz2
scala-edee27f59f17873b378d96504d0b20013a31d081.zip
SI-6168 Retain prefix when parsing types in JVM signatures
When reading Java classfiles, the generic signatures are used to construct the corresponding Scala type signatures. In the enclosed test case, the field `SomeClass.f` had the JVM signature: LContext<LSomeClass;>.Field<Ljava.lang.Integer;>; The parser first (correctly) parsed the prefix as `Context[SomeClass]`. It then looked up the type symbol for `Field` in that that type. It then discarded the parsed prefix, and instead used the prefix from the info of the type symbol: `Context[ParentType]`. This commit changes the signature parser after the first `.` to use the result of prior parsing as the prefix. I've also included a test case with Java static inner classes, which don't require any special treatment.
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala8
-rw-r--r--test/files/run/t6168/Context.java34
-rw-r--r--test/files/run/t6168/JavaTest.java8
-rw-r--r--test/files/run/t6168/SomeClass.java14
-rw-r--r--test/files/run/t6168/SomeClass2.java12
-rw-r--r--test/files/run/t6168/main.scala15
-rw-r--r--test/files/run/t6168b/Context.java34
-rw-r--r--test/files/run/t6168b/JavaTest.java6
-rw-r--r--test/files/run/t6168b/SomeClass.java11
-rw-r--r--test/files/run/t6168b/main.scala8
10 files changed, 149 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index d26a61f187..30851f1d46 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -607,6 +607,8 @@ abstract class ClassfileParser {
val sym = getOwner(jflags).newValue(name.toTermName, NoPosition, sflags)
val isEnum = (jflags & JAVA_ACC_ENUM) != 0
+ // Note: the info may be overrwritten later with a generic signature
+ // parsed from SignatureATTR
sym setInfo {
if (isEnum) ConstantType(Constant(sym))
else info
@@ -661,6 +663,8 @@ abstract class ClassfileParser {
}
info = MethodType(newParams, clazz.tpe)
}
+ // Note: the info may be overrwritten later with a generic signature
+ // parsed from SignatureATTR
sym.setInfo(info)
importPrivateWithinFromJavaFlags(sym, jflags)
parseAttributes(sym, info)
@@ -754,7 +758,9 @@ abstract class ClassfileParser {
accept('.')
val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
val clazz = tpe.member(name)
- tpe = processClassType(processInner(clazz.tpe))
+ val dummyArgs = Nil // the actual arguments are added in processClassType
+ val inner = typeRef(pre = tpe, sym = clazz, args = dummyArgs)
+ tpe = processClassType(inner)
}
accept(';')
tpe
diff --git a/test/files/run/t6168/Context.java b/test/files/run/t6168/Context.java
new file mode 100644
index 0000000000..e527844563
--- /dev/null
+++ b/test/files/run/t6168/Context.java
@@ -0,0 +1,34 @@
+public class Context<ParentType> {
+ private ParentType parent;
+
+ public Context() {}
+
+ public ParentType getParent() {
+ return parent;
+ }
+
+ public void setParent(ParentType parent) {
+ this.parent = parent;
+ }
+
+ public Field<Integer> intField() {
+ return new Field<Integer>() {
+ @Override
+ public Integer get() {
+ return 0;
+ }
+
+ @Override
+ public ParentType set(Integer t) {
+ return parent;
+ }
+ };
+ }
+
+ public abstract class Field<T> { //Note this is a path dependent type
+
+ public abstract T get();
+
+ public abstract ParentType set(T t);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/JavaTest.java b/test/files/run/t6168/JavaTest.java
new file mode 100644
index 0000000000..94ae91661d
--- /dev/null
+++ b/test/files/run/t6168/JavaTest.java
@@ -0,0 +1,8 @@
+public class JavaTest {
+ public static void main(String[] args) {
+ SomeClass a = new SomeClass();
+ SomeClass2 a2 = new SomeClass2();
+ SomeClass b = a.f.set(23).f.set(23);
+ SomeClass2 b2 = a2.f.set(23).f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/SomeClass.java b/test/files/run/t6168/SomeClass.java
new file mode 100644
index 0000000000..6f76b829bb
--- /dev/null
+++ b/test/files/run/t6168/SomeClass.java
@@ -0,0 +1,14 @@
+public class SomeClass {
+ private final Context<SomeClass> context = new Context<SomeClass>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context<SomeClass>.Field<Integer> f = context.intField();
+
+ public SomeClass() {
+ f.set(23).f.set(23);
+ }
+}
+
+
diff --git a/test/files/run/t6168/SomeClass2.java b/test/files/run/t6168/SomeClass2.java
new file mode 100644
index 0000000000..b2c7a7540b
--- /dev/null
+++ b/test/files/run/t6168/SomeClass2.java
@@ -0,0 +1,12 @@
+public class SomeClass2 {
+ private final Context<SomeClass2> context = new Context<SomeClass2>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context<SomeClass2>.Field<Integer> f = context.intField();
+
+ public SomeClass2() {
+ f.set(23).f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/main.scala b/test/files/run/t6168/main.scala
new file mode 100644
index 0000000000..c7ad37830b
--- /dev/null
+++ b/test/files/run/t6168/main.scala
@@ -0,0 +1,15 @@
+
+
+object Test extends App {
+ JavaTest.main(null)
+
+ var a1 : SomeClass = new SomeClass
+ var a2 : SomeClass2 = new SomeClass2
+ //import language.implicitConversions
+ //implicit def setParentType2SomeClass(x:Any) = x.asInstanceOf[SomeClass]
+ //implicit def setParentType2SomeClass2(x:Any) = x.asInstanceOf[SomeClass2]
+ //var b : SomeClass = a.f.set(23).asInstanceOf[SomeClass].f.set(23).asInstanceOf[SomeClass]
+ //var b2 : SomeClass2 = a2.f.set(23).asInstanceOf[SomeClass2].f.set(23).asInstanceOf[SomeClass2]
+ var b1 : SomeClass = a1.f.set(23).f.set(23)
+ var b2 : SomeClass2 = a2.f.set(23).f.set(23)
+}
diff --git a/test/files/run/t6168b/Context.java b/test/files/run/t6168b/Context.java
new file mode 100644
index 0000000000..b3ea22126f
--- /dev/null
+++ b/test/files/run/t6168b/Context.java
@@ -0,0 +1,34 @@
+public class Context<ParentType> {
+ private ParentType parent;
+
+ public Context() {}
+
+ public ParentType getParent() {
+ return parent;
+ }
+
+ public void setParent(ParentType parent) {
+ this.parent = parent;
+ }
+
+ public Field<Integer> intField() {
+ return new Field<Integer>() {
+ @Override
+ public Integer get() {
+ return 0;
+ }
+
+ @Override
+ public ParentType set(Integer t) {
+ return parent;
+ }
+ };
+ }
+
+ public static abstract class Field<T> {
+
+ public abstract T get();
+
+ public abstract Object set(T t);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168b/JavaTest.java b/test/files/run/t6168b/JavaTest.java
new file mode 100644
index 0000000000..a09fa0382d
--- /dev/null
+++ b/test/files/run/t6168b/JavaTest.java
@@ -0,0 +1,6 @@
+public class JavaTest {
+ public static void main(String[] args) {
+ SomeClass a = new SomeClass();
+ Object b = a.f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168b/SomeClass.java b/test/files/run/t6168b/SomeClass.java
new file mode 100644
index 0000000000..566c55e1c5
--- /dev/null
+++ b/test/files/run/t6168b/SomeClass.java
@@ -0,0 +1,11 @@
+public class SomeClass {
+ private final Context<SomeClass> context = new Context<SomeClass>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context.Field<Integer> f = context.intField();
+
+}
+
+
diff --git a/test/files/run/t6168b/main.scala b/test/files/run/t6168b/main.scala
new file mode 100644
index 0000000000..187e9fe85e
--- /dev/null
+++ b/test/files/run/t6168b/main.scala
@@ -0,0 +1,8 @@
+
+
+object Test extends App {
+ JavaTest.main(null)
+
+ var a1 : SomeClass = new SomeClass
+ var b1 : Object = a1.f.set(23)
+}