As I guessed in this thread, the compiler seems to inject an additional comparison that uses a synthetic $outer
reference to exclusively match on inner class instances belonging to the proper outer instance in the pattern match case.
10: checkcast #13 // class Runner$Y$X
13: invokevirtual #40 // Method Runner$Y$X.Runner$Y$X$$$outer:()LRunner$Y;
16: aload_0
17: if_acmpne 35
20: getstatic #46 // Field scala/Predef$.MODULE$:Lscala/Predef$;
23: ldc #48 // String pattern match succeeds, it is the same class
25: invokevirtual #51 // Method scala/Predef$.println:(Ljava/lang/Object;)V
To me it makes sense that the compiler tries to give stronger guarantees for pattern matches than for reflection level comparisons.