1

Given the following object:

object Foo {
  val bar: List[Int] = List(1, 2, 3)
}

When we compile this file to JVM bytecode, because of type erasure and due to the fact that Java does not support primitive types as parameters for generic types, this gets translated into a List<Object>.

We can see this by compiling and inspecting the .class with javap -l:

public static com.yuvalitzchakov.github.Foo$ MODULE$;
  descriptor: Lcom/yuvalitzchakov/github/Foo$;
  flags: ACC_PUBLIC, ACC_STATIC

public scala.collection.immutable.List<java.lang.Object> bar();
  descriptor: ()Lscala/collection/immutable/List;
  flags: ACC_PUBLIC
  Code:
    stack=1, locals=1, args_size=1
        0: aload_0
        1: getfield      #19                 // Field bar:Lscala/collection/immutable/List;
        4: areturn
      LineNumberTable:
        line 4: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/yuvalitzchakov/github/Foo$;
    Signature: #17                          // ()Lscala/collection/immutable/List<Ljava/lang/Object;>;

But, if we compile this into a JAR file and later take it as a dependency in a different Scala project and try to set Foo.bar to a different value, the Scala compiler will infer this type as List[Int], not List[Object]:

Type after taking a dependency on packaged JAR

After browsing around the .class file, I could not find the information on the type parameter which would allow the Scala compiler to successfully infer this as List[Int].

Where is this metadata stored such that we can refer to this type as an actual List[Int] instead of List[Object]?

4

1 回答 1

3

JVM 类文件格式允许编译器将自定义属性放入类文件中,请参阅Java 虚拟机规范第 4.7.1 节。除此之外,Scala 编译器将有关名称的 Scala 签名的信息放入它生成的类文件中,以便在以后的编译器运行时,它可以再次读取此信息。Java 虚拟机需要忽略它们不理解的属性,因此这在运行时不会产生影响。

我没有找到注释的二进制格式规范,但是如果您想深入研究实现,我发现:

对于 Scala 3.0,甚至计划使用新的“美味”格式将包括类型检查器生成的信息在内的完整抽象语法树存储在类文件中。Tasty 代表“类型化抽象语法树”。其基本思想是在类型检查阶段之后将抽象语法树序列化并放入类文件中。稍后的编译器运行可以加载依赖项的完整抽象语法。这不仅可以进行类型检查,还可以进行跨模块内联和其他全局优化。

Tasty 计划成为 Scala 抽象语法树的通用交换格式,也用于编译器和集成开发环境之间的通信以及元编程。

如果您想深入研究实现,也许https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/core/tasty中的文件是一个好的开始。

于 2018-11-21T22:19:58.750 回答