- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Case classes and optimisation
Tue, 2011-08-30, 10:33
I'm currently looking at getting Borachio (the mocking library I'm working on) to support case classes. In the process, I've seen some surprising behaviour that I think I can attribute to calls to the implicitly defined methods being optimised away?
So, for example, given the following class definition:
> case class CaseClass(x: Int, y: String)
The following (hopefully self-explanatory?) test fails because CaseClass.apply is never called:
> test("case class") {
> val m = mock[CaseClass]
> val mo = mockObject(CaseClass)
>
> mo.expects.apply(42, "foo") returning m
>
> CaseClass(42, "foo")
> }
This, by contrast, does pass ("newInstance" is Borachio's way of mocking constructor invocation):
> test("case class") {
> val m = mock[CaseClass]
>
> m.expects.newInstance(42, "foo")
>
> CaseClass(42, "foo")
> }
Sure enough, when I look at the bytecode, I can't find any evidence of apply being called.
Along similar lines, the following also fails:
> test("case class") {
> val m = mock[CaseClass]
> val mo = mockObject(CaseClass)
>
> mo.expects.unapply(CaseClass(3, "bar")) returning Some(3, "bar")
> CaseClass(3, "bar") match {
> case CaseClass(x, y) => assert(x == 3 && y == "bar")
> }
> }
And when I look at the bytecode, I can't find any evidence of unapply being called.
Firstly - have I got this right. Are these method invocations optimised away? Or am I missing something?
Secondly - is there any way to switch these optimisations off?
Thanks,
--
paul.butcher->msgCount++
Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?
http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Tue, 2011-08-30, 11:27
#2
Re: Case classes and optimisation
On Tue, Aug 30, 2011 at 11:55 AM, Sébastien Doeraene <sjrdoeraene@gmail.com> wrote:
Hi,These operations are indeed optimized away. AFAIK there is not way to deactivate this.
You don't need to look at the bytecode to verify this. Just use the -Xprint:cleanup option of the compiler:
$ scalac -Xprint:cleanup Test.scala
You'll see that, indeed, apply is optimized away:
final object Test extends java.lang.Object with ScalaObject {
def main(args: Array[java.lang.String]): Unit = {
val obj: CaseClass = new CaseClass(1, "ABC");
scala.this.Predef.println(scala.Int.box(obj.x()))
};
def this(): object Test = {
Test.super.this();
()
}
}
Now I do not know whether it's possible to deactivate this.
Cheers,
Sébastien
On Tue, Aug 30, 2011 at 11:33, Paul Butcher <paul@paulbutcher.com> wrote:
I'm currently looking at getting Borachio (the mocking library I'm working on) to support case classes. In the process, I've seen some surprising behaviour that I think I can attribute to calls to the implicitly defined methods being optimised away?
So, for example, given the following class definition:
> case class CaseClass(x: Int, y: String)
The following (hopefully self-explanatory?) test fails because CaseClass.apply is never called:
> test("case class") {
> val m = mock[CaseClass]
> val mo = mockObject(CaseClass)
>
> mo.expects.apply(42, "foo") returning m
>
> CaseClass(42, "foo")
> }
This, by contrast, does pass ("newInstance" is Borachio's way of mocking constructor invocation):
> test("case class") {
> val m = mock[CaseClass]
>
> m.expects.newInstance(42, "foo")
>
> CaseClass(42, "foo")
> }
Sure enough, when I look at the bytecode, I can't find any evidence of apply being called.
Along similar lines, the following also fails:
> test("case class") {
> val m = mock[CaseClass]
> val mo = mockObject(CaseClass)
>
> mo.expects.unapply(CaseClass(3, "bar")) returning Some(3, "bar")
> CaseClass(3, "bar") match {
> case CaseClass(x, y) => assert(x == 3 && y == "bar")
> }
> }
And when I look at the bytecode, I can't find any evidence of unapply being called.
Firstly - have I got this right. Are these method invocations optimised away? Or am I missing something?
Secondly - is there any way to switch these optimisations off?
Thanks,
-- Martin
Tue, 2011-08-30, 11:37
#3
Re: Case classes and optimisation
Thanks Sébastien, Martin,
At least I don't need to worry that it's not working because of anything I'm doing wrong :-)
On 30 Aug 2011, at 11:20, martin odersky wrote:
> These operations are indeed optimized away. AFAIK there is not way to deactivate this.
--
paul.butcher->msgCount++
Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?
http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
You don't need to look at the bytecode to verify this. Just use the -Xprint:cleanup option of the compiler:
$ scalac -Xprint:cleanup Test.scala
You'll see that, indeed, apply is optimized away:
Now I do not know whether it's possible to deactivate this.
Cheers,
Sébastien
On Tue, Aug 30, 2011 at 11:33, Paul Butcher <paul@paulbutcher.com> wrote: