Description
Compiler version
3.5.0, 3.5.1
Minimized code
This is a follow-up on an issue reported by Tomassino on the Scala users.scala-lang.org forum.
I created this small demo Github project to showcase this issue: https://github.com/jrlemieux/scala-weird
The two classes Test1 and Test2 inherit common code that is calling their virtual partial function outerPf_2.
The only difference between the two classes is the commenting of the useless statement "val something = p".
class Test1() extends TestTrait:
val outerPf_2: PartialFunction[Any, Any] = p =>
val something = p
innerPf(p) match
case Some(_) => println("Something")
class Test2() extends TestTrait:
val outerPf_2: PartialFunction[Any, Any] = p =>
// val something = p
innerPf(p) match
case Some(_) => println("Something")
Expectation
It was expected that Test1.outerPf_2 would behave exactly as Test2.outerPf_2, but it doesn't.
The compiler generates very different code for the isDefinedAt method of the outerPf_2 partial functions.
For Test1:
public final boolean isDefinedAt(java.lang.Object);
Code:
0: aload_1
1: astore_2
2: iconst_1
3: ireturn
For Test2:
public final boolean isDefinedAt(java.lang.Object);
Code:
0: aload_0
1: getfield #24 // Field $outer:Lcom/playzone/some-common-name;
4: invokevirtual #33 // Method com/playzone/some-common-name.innerPf:()Lscala/PartialFunction;
7: aload_1
8: invokeinterface #39, 2 // InterfaceMethod scala/PartialFunction.apply:(Ljava/lang/Object;)Ljava/lang/Object;
13: checkcast #41 // class scala/Option
16: astore_2
17: aload_2
18: instanceof #43 // class scala/Some
21: ifeq 26
24: iconst_1
25: ireturn
26: iconst_0
27: ireturn
The difference might be due to the fact that one PF is inlining code. But whether the compiler optimizes with inlining or not should not affect the behavior of the code. Adding an extra useless assignment statement should not affect the code's behavior.