Capture o problema de conversão em Java, reconciliação WRT do JLS e o comportamento real do JDK
Dadas as seguintes duas definições de classe:
class C1<T extends C1<T>> {}
class C2<U> extends C1<C2<U>> {}
Considere a seguinte declaração de tipo:
C1<? extends C2<String>> c;
Isso compila bem no JDK-8u45, mas se examinarmos oespecificação para conversão de captura, parece (para mim) que esta declaraçãodevemos resultar em um erro de tempo de compilação.
Em particular, o limite superior do novo tipo de captura de variávelT#1
É dado porglb(Bi, Ui[A1:=S1,...,An:=Sn])
, onde neste casoBi
resolve para o curinga ligadoC2<String>
eUi[A1:=S1,...,An:=Sn]
resolveC1<T#1>
.
A partir disso,glb(C2<?>, C1<T#1>)
resolve para o tipo de interseçãoC2<String> & C1<T#1>
, que é inválido porqueC2<String>
eC1<T#1>
são dois tipos de classe, não de interface, mas nenhum deles é um subtipo do outro.
Essa violação (aparente) da regra talvez seja mais clara nodefinição do tipo de interseção em si.
Tenho certeza que não é um bug e só estou cometendo alguns erros simples em algum lugar ... Se for um bug, espero que possa ser considerado um bug no JLS e não no JDK, de modo que eu possa poder emular com segurança o comportamento ...
Obrigado por qualquer ajuda!
Editar: Depois de conversar com Radiodef ontem, me convenci de que o problema (ou pelo menos uma maneira de vê-lo) é queC2<String>
pode efetivamente ser pensado como um subtipo deC1<T#1>
, já que o T # 1 pode apenassempre ser satisfeito porC2<String>
e, portanto, pode ser considerado igual a ele, mas as regras de contenção e subtipagem não entendem esse relacionamento como escrito e, portanto, o JLS não reconhecerá o subtipo e deve falhar ...
Se você considerar o caso um pouco mais complexo deC1<? extends C2<?>> d;
, porém, é mais complicado. O problema é semelhante, mas o tipo de interseção que forma o limite superior da captura sai comoC2<?> & C1<T#2>
, onde não parece que uma solução possa ser encontrada pelo mesmo raciocínio acima.