Java, 102 95 89 88 78 bytes
class A<T>{}class B<T>extends A<A<?super B<B<T>>>>{A<?super B<A>>a=new B<>();}
Isso termina com o StackOverflowError
que acontece porque o sistema de resolução genérico não pode decidir uma raiz na qual resolver os outros genéricos.
Créditos quando vencidos .
o que acontece aqui?
A<T>
está lá apenas para ter um pai de uma letra. É genérico. Eu poderia ter usado List
, mas as importações e a repetição de 4 letras são muito longas.
B<T>
declara um genérico básico.
B extends A
é necessário ter uma hierarquia entre B
e A
.
extends A<A>
cria uma auto-referência em A<T>
.
A<? super B>
aciona a pesquisa de genéricos em A<T>
B<B<T>>
cria uma auto-referência em B<T>
.
A<...> a=new B<>()
força o uso dos genéricos, em vez de simplesmente defini-los, forçando a resolução ao compilar B
e não posteriormente.
A<?super B
cria uma não referência própria, portanto, temos uma referência a um tipo e a outro nos genéricos de A
.
B<A>
cria uma não referência própria, portanto, temos uma referência a um tipo e a outro nos genéricos de B
.
Agora, o tipo A
tem o tipo genérico A
e B
, mas qual deve ser escolhido? Esqueça a si mesmo, vamos tentar resolver B
. Ping.
Ok, B
tem o tipo de genéricos A
e B
, mas qual deve ser escolhido? Esqueça a si mesmo, vamos tentar resolver A
. Pong.
Este tipo de recursão não pode realmente ser evitada porque há casos legítimos como A<B<A<B<A<B<Object>>>>>>
: por exemplo, um objeto JSON: List<Map<String,Map<String,List<Map<String,List<String>>>>>>
.
Resultado da compilação
$ javac NoCompile.java
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:3260)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2587)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2579)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:554)
at com.sun.tools.javac.code.Types$UnaryVisitor.visit(Types.java:3260)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2592)
at com.sun.tools.javac.code.Types$23.visitClassType(Types.java:2579)
at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:554)
No meu sistema, o rastreamento da pilha para depois de mostrar 1024 linhas, que são na verdade as 4 mesmas linhas repetidas 256 vezes, provando uma recursão infinita. Vou poupar todo esse vestígio.
Poupança
- 102 → 95 bytes: substituído
interface
+ implements
por class
+ extends
.
- 95 → 89 bytes: substituído
Long
por A
(duas vezes).
- 89 → 88 bytes: operador de diamante usado (
new B<A>()
→ new B<>()
).
- 88 → 78 bytes: moveu a declaração da variável para um membro da classe, graças a VoteToClose .