Информация о типе для примитивных типов в полиморфных типах - PullRequest
0 голосов
/ 21 ноября 2018

Учитывая следующий объект:

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

После просмотра файла .class я не смог найти информацию о параметре type, которая позволила бы компилятору Scala успешно вывести это как List[Int].

* 1025.* Где хранятся эти метаданные, чтобы мы могли ссылаться на этот тип как на фактический List[Int] вместо List[Object]?

1 Ответ

0 голосов
/ 22 ноября 2018

Формат файла класса JVM позволяет компиляторам помещать пользовательские атрибуты в файл класса, см. Раздел 4.7.1 Спецификация виртуальной машины Java .Помимо прочего, компилятор Scala помещает информацию о сигнатуре имен Scala в генерируемые им файлы классов, чтобы при последующем запуске компилятора он мог снова прочитать эту информацию.Виртуальные машины Java обязаны игнорировать атрибуты, которые они не понимают, поэтому это не имеет значения во время выполнения.

Я не нашел спецификации двоичного формата для аннотаций, но если вы хотитеЧтобы углубиться в реализацию, я нашел:

Для Scala 3.0Планируется даже сохранить полное абстрактное синтаксическое дерево, включая информацию, сгенерированную средством проверки типов, в файлах классов с использованием нового «вкусного» формата.Tasty означает «типизированные деревья абстрактного синтаксиса».Основная идея состоит в том, чтобы сериализовать абстрактное синтаксическое дерево после фазы проверки типов и поместить его в файлы классов.Последующие запуски компилятора могут затем загрузить полный абстрактный синтаксис зависимостей.Это может позволить не только проверку типов, но и межмодульное встраивание и другие глобальные оптимизации.

Планируется, что Tasty станет универсальным форматом обмена для абстрактных синтаксических деревьев Scala, а также для связи между компилятором и интегрированной разработкойокружения и метапрограммирование.

Если вы хотите углубиться в реализацию, возможно, файлы в https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/core/tasty - хорошее начало.

...