summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2012-07-01 12:42:42 +0200
committerJason Zaugg <jzaugg@gmail.com>2012-07-01 12:54:12 +0200
commitad51d8295388c02ca9160177aaba1b7e490eb5c2 (patch)
treea532bdebce0f4b3ef316fa3635e684b927710b71
parent0a9cea6ea58571deb67d60193d60d12be6bb0233 (diff)
downloadscala-ad51d8295388c02ca9160177aaba1b7e490eb5c2.tar.gz
scala-ad51d8295388c02ca9160177aaba1b7e490eb5c2.tar.bz2
scala-ad51d8295388c02ca9160177aaba1b7e490eb5c2.zip
SI-5489 Avoid accidentally adding members to Object in erasure.
`Symbol#classBound` assumed that `refinedType` would return a a type based on new refinement class symbol; but that isn't so during erasure. Instead, it returns the first super class, into which we entered new members. Needless to say, the next run of the resident compiler didn't take kindly to these hijinks. To remedy the situation, I've added (yet another) condition on `phase.erasedTypes`.
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala38
-rw-r--r--test/files/res/t5489.check4
-rw-r--r--test/files/res/t5489.res2
-rw-r--r--test/files/res/t5489/t5489.scala14
4 files changed, 41 insertions, 17 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index a3893a0236..79041924a8 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -1438,24 +1438,28 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def classBound: Type = {
val tp = refinedType(info.parents, owner)
- val thistp = tp.typeSymbol.thisType
- val oldsymbuf = new ListBuffer[Symbol]
- val newsymbuf = new ListBuffer[Symbol]
- for (sym <- info.decls) {
- // todo: what about public references to private symbols?
- if (sym.isPublic && !sym.isConstructor) {
- oldsymbuf += sym
- newsymbuf += (
- if (sym.isClass)
- tp.typeSymbol.newAbstractType(sym.name.toTypeName, sym.pos).setInfo(sym.existentialBound)
- else
- sym.cloneSymbol(tp.typeSymbol))
+ // SI-4589 refinedType only creates a new refinement class symbol before erasure; afterwards
+ // the first parent class is returned, to which we must not add members.
+ if (!phase.erasedTypes) {
+ val thistp = tp.typeSymbol.thisType
+ val oldsymbuf = new ListBuffer[Symbol]
+ val newsymbuf = new ListBuffer[Symbol]
+ for (sym <- info.decls) {
+ // todo: what about public references to private symbols?
+ if (sym.isPublic && !sym.isConstructor) {
+ oldsymbuf += sym
+ newsymbuf += (
+ if (sym.isClass)
+ tp.typeSymbol.newAbstractType(sym.name.toTypeName, sym.pos).setInfo(sym.existentialBound)
+ else
+ sym.cloneSymbol(tp.typeSymbol))
+ }
+ }
+ val oldsyms = oldsymbuf.toList
+ val newsyms = newsymbuf.toList
+ for (sym <- newsyms) {
+ addMember(thistp, tp, sym modifyInfo (_ substThisAndSym(this, thistp, oldsyms, newsyms)))
}
- }
- val oldsyms = oldsymbuf.toList
- val newsyms = newsymbuf.toList
- for (sym <- newsyms) {
- addMember(thistp, tp, sym modifyInfo (_ substThisAndSym(this, thistp, oldsyms, newsyms)))
}
tp
}
diff --git a/test/files/res/t5489.check b/test/files/res/t5489.check
new file mode 100644
index 0000000000..6cf64f734b
--- /dev/null
+++ b/test/files/res/t5489.check
@@ -0,0 +1,4 @@
+
+nsc>
+nsc>
+nsc>
diff --git a/test/files/res/t5489.res b/test/files/res/t5489.res
new file mode 100644
index 0000000000..5b787b7765
--- /dev/null
+++ b/test/files/res/t5489.res
@@ -0,0 +1,2 @@
+t5489/t5489.scala
+t5489/t5489.scala \ No newline at end of file
diff --git a/test/files/res/t5489/t5489.scala b/test/files/res/t5489/t5489.scala
new file mode 100644
index 0000000000..f821a1a9b6
--- /dev/null
+++ b/test/files/res/t5489/t5489.scala
@@ -0,0 +1,14 @@
+package repro
+
+trait HasString {
+ def blerg(): String
+}
+
+class CausesProblems {
+ def problems = (
+ if ("don't optimize me away!".length == 0)
+ new HasString { def blerg() = "wut" }
+ else
+ new HasString { def blerg() = "okay" }
+ ).blerg()
+}