summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2012-11-17 22:04:19 +0100
committerJason Zaugg <jzaugg@gmail.com>2012-11-18 14:31:14 +0100
commit2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87 (patch)
tree7a23a472768adad7bd060ed1cb5119a004414297 /src/compiler
parent2d62ab248d07f10fd89a68b12565259ca861e1e9 (diff)
downloadscala-2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87.tar.gz
scala-2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87.tar.bz2
scala-2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87.zip
SI-6677 Insert required cast in `new qual.foo.T`
Short version: we sometimes need to rewrite this as new T(qual.asInstanceOf[OwnerOfFoo].foo) Long version: `adaptMember` in Erasure performs a few tasks, among them: 1. adding an empty argument list to qualifiers in `new qual.T` for which `qual` is a val template member that has (post uncurry) a MethodType with an empty parameter list. The same rewriting was already applied in uncurry for such qualifiers appearing in other contexts, e.g. `qual.foo` was already rewritten to `qual().foo`. 2. casting, if necessary, the qualifier in `Select(qual, name)` to the type of owner of the symbol that this selection references. This can be neccesary with compound types: - some val class member has type `A with B`; - we instantiate `new ab.valMemberOfB.T` - we must pass `ab.valMemberOfB` to the constructor of `T` as the `$outer` pointer - we must cast `ab` to `B` before calling `valMemberOfB`. Failure to insert this cast can lead to a LinkageError or a VerifyError. However, if 1) was performed, 2) was not. The error is pretty easy to trigger with the new reflection API: class Test { val cm: reflect.runtime.universe.Mirror = reflect.runtime.currentMirror def error { new cm.universe.Traverser // java.lang.VerifyError } def okay1 { val cm: reflect.runtime.universe.Mirror = reflect.runtime.currentMirror new cm.universe.Traverser } } The fix applied here to `adaptMember` mirrors the existing implementation of `adaptType`.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala1
1 files changed, 1 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 7b45b3efe5..d66a0dd3f6 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -788,6 +788,7 @@ abstract class Erasure extends AddInterfaces
else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) {
assert(qual1.symbol.isStable, qual1.symbol);
qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
+ return adaptMember(treeCopy.Select(tree, qual1, name))
} else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
assert(tree.symbol.owner != ArrayClass)
qual1 = cast(qual1, tree.symbol.owner.tpe)