Почему следующий код аварии javac? Что можно сделать по этому поводу?

Я читал эту статью о "странных вещах в Java", и я наткнулся на интересную концепцию: Undecidable types.

Рассмотрим следующие три класса/интерфейсов:

public interface Type<T> { }
public class D<P> implements Type<Type<? super D<D<P>>>> { }
public class WildcardTest {
  Type<? super D<Byte>> d = new D<Byte>();
}

По-видимому, проблема в том, что она неразрешима, является ли D a Type<? super D<Byte>>; может ли кто-нибудь объяснить это дальше?

javac 1.8.0_60 выдает очень длинный StackOverflowError при попытке скомпилировать WildcardTest:

The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3834)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
        at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
        at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
        at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)
        at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:4640)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3839)
        at com.sun.tools.javac.code.Types$26.visitClassType(Types.java:3826)
        at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)

Этот код также разбивает всю среду Eclipse.

Автор отправил сообщение об ошибке с командой Eclipse, но он не получил никаких голосов (кроме моих). Можно ли что-нибудь сделать? Это просто проблема закрытия в форме компилятора?

В статье есть ссылка на эту статью, но я надеюсь, что есть более простое объяснение.

Ответ 1

Как отметил в комментариях Тунаки в комментариях, это относится к исследовательской работе Microsoft, соавтором которой является Пирс (автор TAPL). На самом деле проблема Tate et al. дайте пример 2 из Приложения A (с Byte = T, Type = N и D = C).

Переполнение стека

Во-первых, давайте выясним, почему он ударяет стек. Для этого хорошо напоминать себе, что компилятор проверяет типы почти так же, как и мы. Проблемы, с которыми мы сталкиваемся, будут встречаться.

// To be determined:
D<Byte> <: Type<? super D<Byte>>

// using D<P> implements Type<Type<? super D<D<P>>>>

Type<Type<? super D<D<Byte>>>> <: Type<? super D<Byte>>

// The outermost type constructor (Type) matches. For the
// suptyping relationship to hold, we have to test the type
// arguments. (Sides are flipped due to contravariance.)

D<Byte> <: Type<? super D<D<Byte>>>

// Mhh… That looks an awful lot like above.
// Feel free to rinse and repeat until your "stack" blows too… ;)

Pierce et al. описать аналогичный регресс, как в примере 2 в разделе 3 их статьи. Это немного отличается, потому что Java не допускает нижних границ переменных типа, только на подстановочных знаках.

Что можно сделать?

Подобно примеру 1, данному Pierce et al., эта регрессия следует схеме. Этот шаблон может быть обнаружен компилятором, и можно предположить, что отношение подтипирования сохраняется под коиндуктивной интерпретацией. (Это те же рассуждения, что и с F-ограниченным полиморфизмом, т.е. Enum<E extends Enum<E>>. Вы вводите подобный бесконечный регресс без противоречия.)

Неразрешимые?

Данную проблему можно решить с помощью более разумного алгоритма. Независимо от того, является ли система типа Java разрешимой или нет, остается открытым вопрос.

Если Java допускает нижние границы параметров типа, он будет неразрешимым (полу разрешаемым). Однако в своей работе Pierce et al. определить ограничения, с помощью которых такая система типов может быть снова разрешима. Кстати, эти ограничения были приняты Scala, который по иронии судьбы имеет систему полного типа turing.