From 2aa68419c09ba16e4e7fdc71e4a3ad9e8b261e87 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 17 Nov 2012 22:04:19 +0100 Subject: 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`. --- test/files/run/t6677b.scala | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/files/run/t6677b.scala (limited to 'test/files/run/t6677b.scala') diff --git a/test/files/run/t6677b.scala b/test/files/run/t6677b.scala new file mode 100644 index 0000000000..e4fe5e3722 --- /dev/null +++ b/test/files/run/t6677b.scala @@ -0,0 +1,33 @@ +trait U { + trait U1 { + class X + } + type U11 <: U1 + val u : U11 = null.asInstanceOf[U11] +} +trait A extends U + +trait B extends U { + def foo = "" + class U11 extends U1 { class X extends super.X { foo } } // refer to foo to add $outer pointer + override val u = new U11 +} +class C { + val ab: A with B = new A with B // `B with A` works. + + def foo { + // fails + new ab.u.X + + // works: + val u = ab.u + new u.X + } +} +object Test { + def main(args: Array[String]) { + // java.lang.NoSuchMethodError: A.u()LB$U11; + // at C.foo(t6677b.scala:23) + new C().foo + } +} -- cgit v1.2.3