Non ho la risposta completa al 100%, ma ho un puntatore che potrebbe essere sufficiente per te.
Il compilatore Scala si occupa dei GADT (tipi di dati algebrici generalizzati) in un modo molto particolare. Alcuni casi sono risolti con una gestione speciale, alcuni casi sono irrisolti. Dotty sta cercando di colmare la maggior parte dei buchi, e ha già risolto molti problemi correlati, tuttavia ce ne sono ancora alcuni aperti .
Un tipico esempio di gestione GADT speciale nel compilatore Scala 2 è molto correlato al tuo caso d'uso. Se diamo un'occhiata a:
def method[A](arg: Base[A]) = {
arg match {
case Derived(_) => 42
}
}
e dichiariamo esplicitamente che il tipo restituito è A
:
def method[A](arg: Base[A]): A
compilerà bene. Il tuo IDE potrebbe lamentarsi, ma il compilatore lo farà passare. Il metodo dice che restituisce un A
, ma il caso di corrispondenza del modello viene valutato in un Int
, che teoricamente non dovrebbe essere compilato. Tuttavia, la gestione speciale dei GADT nel compilatore dice che va bene, perché in quel particolare ramo di corrispondenza del modello A
è stato "riparato" per essere un Int
(perché abbiamo abbinato suDerived
quale è unBase[Int]
).
Il parametro di tipo generico per GADT (nel nostro caso A
) deve essere dichiarato da qualche parte. Ed ecco la parte interessante: la gestione speciale del compilatore funziona solo quando viene dichiarata come parametro di tipo del metodo allegato . Se proviene da un membro del tipo o da un parametro del tipo del tratto / classe allegato, non si compila, come hai visto tu stesso.
Questo è il motivo per cui ho detto che non è una risposta completa al 100%: non posso indicare un luogo concreto (come una specifica ufficiale) che lo documenti correttamente. Le fonti sulla gestione dei GADT in Scala si riducono a un paio di blogposts , che sono comunque eccezionali, ma se vuoi qualcosa di più dovrai scavare tu stesso nel codice del compilatore. Ho provato a fare esattamente questo, e penso che dipenda da questo metodo , ma se vuoi davvero andare più in profondità, potresti voler fare un ping a qualcuno più esperto con la base di codice del compilatore Scala.