Closed
Description
When trying to make this Scala.js test works in Dotty https://github.com/scala-js/scala-js/blob/master/test-suite/shared/src/test/scala/org/scalajs/testsuite/javalib/io/ReadersTest.scala#L63
Scala.js linker fails with
[error] Referring to non-existent method java.nio.CharBuffer.slice()java.nio.Buffer
I found that the IR generated is different
in Dotty:
val buf: java.nio.CharBuffer = buf0.slice;Ljava.nio.Buffer().asInstanceOf[java.nio.CharBuffer];
in Scala 2.13:
val buf: java.nio.CharBuffer = buf0.slice;Ljava.nio.CharBuffer();
minimized code
This is minimized code:
import java.nio.CharBuffer
class test {
val a: CharBuffer = null
val b = a.slice()
}
The class file seems have wrong type in it's constant pool, and will have a checkcast
instruction; see bytecode bellow:
Compilation output
Classfile /Users/molikto/GitHub/dotty/test.class
Last modified Jan 10, 2020; size 600 bytes
MD5 checksum 25414eae76502c40f16327ad77826708
Compiled from "test.scala"
public class test
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #2 // test
super_class: #4 // java/lang/Object
interfaces: 0, fields: 2, methods: 3, attributes: 3
Constant pool:
#1 = Utf8 test
#2 = Class #1 // test
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 test.scala
#6 = Utf8 a
#7 = Utf8 Ljava/nio/CharBuffer;
#8 = Utf8 b
#9 = Utf8 <init>
#10 = Utf8 ()V
#11 = NameAndType #9:#10 // "<init>":()V
#12 = Methodref #4.#11 // java/lang/Object."<init>":()V
#13 = NameAndType #6:#7 // a:Ljava/nio/CharBuffer;
#14 = Fieldref #2.#13 // test.a:Ljava/nio/CharBuffer;
#15 = Utf8 ()Ljava/nio/CharBuffer;
#16 = NameAndType #6:#15 // a:()Ljava/nio/CharBuffer;
#17 = Methodref #2.#16 // test.a:()Ljava/nio/CharBuffer;
#18 = Utf8 java/nio/CharBuffer
#19 = Class #18 // java/nio/CharBuffer
#20 = Utf8 slice
#21 = Utf8 ()Ljava/nio/Buffer;
#22 = NameAndType #20:#21 // slice:()Ljava/nio/Buffer;
#23 = Methodref #19.#22 // java/nio/CharBuffer.slice:()Ljava/nio/Buffer;
#24 = NameAndType #8:#7 // b:Ljava/nio/CharBuffer;
#25 = Fieldref #2.#24 // test.b:Ljava/nio/CharBuffer;
#26 = Utf8 this
#27 = Utf8 Ltest;
#28 = Utf8 Code
#29 = Utf8 LineNumberTable
#30 = Utf8 LocalVariableTable
#31 = Utf8 SourceFile
#32 = Utf8 TASTY
#33 = Utf8 Scala
{
public test();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #12 // Method java/lang/Object."<init>":()V
4: aload_0
5: aconst_null
6: putfield #14 // Field a:Ljava/nio/CharBuffer;
9: aload_0
10: aload_0
11: invokevirtual #17 // Method a:()Ljava/nio/CharBuffer;
14: invokevirtual #23 // Method java/nio/CharBuffer.slice:()Ljava/nio/Buffer;
17: checkcast #19 // class java/nio/CharBuffer
20: putfield #25 // Field b:Ljava/nio/CharBuffer;
23: return
LineNumberTable:
line 3: 0
line 5: 4
line 7: 9
LocalVariableTable:
Start Length Slot Name Signature
0 24 0 this Ltest;
public java.nio.CharBuffer a();
descriptor: ()Ljava/nio/CharBuffer;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #14 // Field a:Ljava/nio/CharBuffer;
4: areturn
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltest;
public java.nio.CharBuffer b();
descriptor: ()Ljava/nio/CharBuffer;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #25 // Field b:Ljava/nio/CharBuffer;
4: areturn
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltest;
}
SourceFile: "test.scala"
Error: unknown attribute
TASTY: length = 0x10
00 B5 CF 56 F8 F6 DC 00 00 05 3A 7B D6 3C 8F 00
Error: unknown attribute
Scala: length = 0x0
This is Tasty file (seems no cast is present here):
Compilation output
0: PACKAGE(78)
2: TERMREFpkg 1 [<empty>]
4: IMPORT(6)
6: SELECT 2 [nio]
8: TERMREFpkg 3 [java]
10: IMPORTED 4 [CharBuffer]
12: TYPEDEF(66) 5 [test]
15: TEMPLATE(48)
17: APPLY(7)
19: SELECT 11 [<init>[Signed Signature(List(),java.lang.Object)]]
21: NEW
22: TYPEREF 9 [Object]
24: TERMREFpkg 8 [java[Qualified . lang]]
26: DEFDEF(6) 6 [<init>]
29: PARAMEND
30: TYPEREF 12 [Unit]
32: TERMREFpkg 13 [scala]
34: VALDEF(8) 14 [a]
37: IDENTtpt 4 [CharBuffer]
39: TYPEREF 4 [CharBuffer]
41: TERMREFpkg 15 [java[Qualified . nio]]
43: NULLconst
44: VALDEF(19) 16 [b]
47: TYPEREF 4 [CharBuffer]
49: TERMREFpkg 15 [java[Qualified . nio]]
51: APPLY(12)
53: SELECT 19 [slice[Signed Signature(List(),java.nio.CharBuffer)]]
55: SELECT 14 [a]
57: QUALTHIS
58: IDENTtpt 5 [test]
60: TYPEREFsymbol 12
62: THIS
63: TYPEREFpkg 1 [<empty>]
65: ANNOTATION(13)
67: TYPEREF 20 [SourceFile]
69: TERMREFpkg 24 [scala[Qualified . annotation][Qualified . internal]]
71: APPLY(7)
73: SELECT 28 [<init>[Signed Signature(List(java.lang.String),scala.annotation.internal.SourceFile)]]
75: NEW
76: SHAREDtype 67
78: STRINGconst 29 [test.scala]
80:
It doesn't seems to happen with similar Scala code:
abstract class Buffer {
def slice(): Buffer
}
abstract class CharBuffer extends Buffer {
override def slice(): CharBuffer
}
class test {
val a: CharBuffer = null
val b = a.slice()
}