代码之家  ›  专栏  ›  技术社区  ›  Yuval Itzchakov

多态类型中基元类型的类型信息

  •  1
  • Yuval Itzchakov  · 技术社区  · 7 年前

    鉴于以下目标:

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

    当我们将此文件编译为JVM字节码时,由于类型擦除以及Java不支持将基元类型作为泛型类型的参数,这会被转换为 List<Object> .

    我们可以通过编译和检查 .class 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;>;
    

    但是,如果我们将其编译成一个JAR文件,然后将其作为另一个Scala项目中的依赖项,并尝试设置 Foo.bar 对于不同的值,Scala编译器将推断该类型为 List[Int] List[Object]

    Type after taking a dependency on packaged JAR

    在浏览完 .类 文件中,我找不到有关类型参数的信息,该参数将允许Scala编译器成功地将其推断为 列表[Int] .

    该元数据存储在何处,以便我们可以将该类型称为实际类型 列表[Int] 而不是 ?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Toxaris    7 年前

    JVM类文件格式允许编译器将自定义属性放入类文件中,请参阅 Section 4.7.1 Java Virtual Machine Specification . 除其他外,Scala编译器将有关名称的Scala签名的信息放入它生成的类文件中,以便在以后的编译器运行时,它可以再次读取这些信息。Java虚拟机需要忽略它们不理解的属性,所以在运行时这并没有什么区别。

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

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

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

    https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/core/tasty 这是一个好的开始。

    推荐文章