Não tenho a resposta 100% completa, mas tenho um ponteiro que pode ser suficiente para você.
O compilador Scala lida com GADTs (tipos de dados algébricos generalizados) de uma maneira muito particular. Alguns casos são resolvidos com tratamento especial, outros não são resolvidos. Dotty está tentando preencher a maioria dos buracos e já resolveu muitos problemas relacionados, no entanto, ainda existem alguns abertos .
O exemplo típico de manipulação especial do GADT no compilador Scala 2 está muito relacionado ao seu caso de uso. Se dermos uma olhada em:
def method[A](arg: Base[A]) = {
arg match {
case Derived(_) => 42
}
}
e declaramos explicitamente o tipo de retorno como A
:
def method[A](arg: Base[A]): A
ele irá compilar muito bem. Seu IDE pode reclamar, mas o compilador o deixará passar. O método diz que retorna um A
, mas o caso de correspondência de padrões é avaliado em um Int
, que teoricamente não deveria ser compilado. No entanto, o tratamento especial de GADTs no compilador diz que não há problema, porque nesse ramo específico de correspondência de padrões A
foi "corrigido" para ser um Int
(porque combinamos com o Derived
que é a Base[Int]
).
O parâmetro de tipo genérico para o GADT (no nosso caso A
) deve ser declarado em algum lugar. E aqui está a parte interessante - o tratamento especial do compilador só funciona quando é declarado como o parâmetro de tipo do método envolvente . Se for proveniente de um membro de tipo ou de um parâmetro de tipo da característica / classe anexa, não será compilado, como você testemunhou.
É por isso que eu disse que não é uma resposta 100% completa - não posso apontar para um local concreto (como a especificação oficial) que documenta isso corretamente. As fontes de manipulação de GADTs no Scala se resumem a alguns posts do blog , o que é ótimo, a propósito, mas se você quiser mais do que isso, precisará pesquisar o código do compilador. Eu tentei fazer exatamente isso, e acho que se resume a esse método , mas se você realmente quiser ir mais fundo, poderá executar ping em alguém mais experiente com a base de código do compilador Scala.