super not working inside an anonymous function (e.g. for loop)

22 views
Skip to first unread message

Tomas Mikula

unread,
Feb 24, 2011, 8:58:49 PM2/24/11
to scala...@googlegroups.com
The following code compiles, but throws ClassCastException when
executed (tested with Scala 2.8.1 and 2.7.7).
I think I understand why it doesn't work (although then I don't
understand why it compiles), but what is the correct way to call
supertype methods from inside a for loop?

Thanks,
Tomas

trait A { def f() = println("A") }
class B extends A { def g() = for(i <- 0 until 1) super[A].f() }
(new B).g()

java.lang.ClassCastException: B$$anonfun$g$1 cannot be cast to A
at B$$anonfun$g$1.apply(<console>:5)
at B$$anonfun$g$1.apply(<console>:5)
at scala.Range.foreach(Range.scala:44)
at B.g(<console>:5)
at .<init>(<console>:7)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:3)
at RequestResult$.<clinit>(<console>)
at RequestResult$result(<console>)
at sun.reflect.Nativ...

Mike

unread,
Feb 24, 2011, 10:52:04 PM2/24/11
to scala...@googlegroups.com
Tomas Mikula wrote:
> trait A { def f() = println("A") }
> class B extends A { def g() = for(i <- 0 until 1) super[A].f() }
> (new B).g()
>
> java.lang.ClassCastException: B$$anonfun$g$1 cannot be cast to A

This looks to me like a compiler bug. The "innermost template" for
super[A].f is B, but the compiled code is trying to use the "this"
reference:

----------
public final class B$$anonfun$g$1 extends
scala.runtime.AbstractFunction1$mcVI$sp implements java.io.Serializable{

public void apply$mcVI$sp(int);
Code:
0: aload_0
1: checkcast #24; //class A
4: invokestatic #30; //Method A$class.f:(LA;)V
7: return
----------

But this works:

class B extends A { b => def g() = for(i <- 0 until 1) b.f() }

Tomas Mikula

unread,
Feb 25, 2011, 11:03:36 AM2/25/11
to scala...@googlegroups.com
Hello Mike,

But if f() is overriden in B, then B.f() is called, not A.f(). So it
does not solve my problem. Consider the following:

trait A { def f() = println("A") }

class B extends A { a: A =>
override def f() = println("B")
def g() = for(i <- 0 until 1) a.f()
}
(new B).g()

The output is:
B

Regards,
Tomas

Mike

unread,
Feb 25, 2011, 4:48:20 PM2/25/11
to scala...@googlegroups.com
Don't forget to report your bug.

Tomas Mikula wrote:
>>> class B extends A { def g() = for(i <- 0 until 1) super[A].f() }
>>

>> class B extends A { b => def g() = for(i <- 0 until 1) b.f() }
>
> But if f() is overriden in B, then B.f() is called, not A.f().

As would be expected in a virtual method invocation.

> class B extends A { a: A =>
> override def f() = println("B")
> def g() = for(i <- 0 until 1) a.f()
> }

class B extends A { b =>
private def super_f() = super[A].f()


override def f() = println("B")

def g() = for(i <- 0 until 1) b.super_f()
}

Tomas Mikula

unread,
Feb 25, 2011, 5:23:04 PM2/25/11
to scala...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages