diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2012-11-17 22:04:19 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2012-11-18 14:31:14 +0100 |
commit | 2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87 (patch) | |
tree | 7a23a472768adad7bd060ed1cb5119a004414297 /src/compiler | |
parent | 2d62ab248d07f10fd89a68b12565259ca861e1e9 (diff) | |
download | scala-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.scala | 1 |
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) |