Se guardiamo a il compilatore di Scala, le fonti potrebbero aiutarci a capire qual è il problema. Non ho mai contribuito al compilatore di Scala, ma ho trovato le fonti molto leggibili e ho già studiato su questo.
La classe responsabile dell'inferenza di tipo è scala.tools.nsctypechecker.Infer
che è possibile trovare semplicemente guardando nelle fonti del compilatore Scala per una parte del proprio errore. Scoprirete il seguente frammento:
/** error if arguments not within bounds. */
def checkBounds(pos: Position, pre: Type, owner: Symbol,
tparams: List[Symbol], targs: List[Type], prefix: String) = {
//@M validate variances & bounds of targs wrt variances & bounds of tparams
//@M TODO: better place to check this?
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
if(!kindErrors.isEmpty) {
error(pos,
prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
" do not conform to the expected kinds of the type parameters "+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
kindErrors.toList.mkString("\n", ", ", ""))
}
Così ora il punto è capire il motivo per cui checkKindBounds(tparams, targs, pre, owner)
restituisce quegli errori.Se si va giù per la catena di chiamata di metodo, si vedrà che i checkKindBounds chiamare un altro metodo
val errors = checkKindBounds0(tparams, targs, pre, owner, true)
Vedrete il problema è collegato alla verifica limiti di tipo alto-kinded, alla riga 5784, all'interno checkKindBoundsHK:
if (!sameLength(hkargs, hkparams)) {
if (arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded
else {error = true; (List((arg, param)), Nil, Nil) } // shortcut: always set error, whether explainTypesOrNot
}
Il test non viene passato, sembra che nel mio debugger:
hkargs$1 = {[email protected]}"List()"
arg$1 = {[email protected]}"class List"
param$1 = {[email protected]}"type B"
paramowner$1 = {[email protected]}"method process"
underHKParams$1 = {[email protected]}"List(type R)"
withHKArgs$1 = {[email protected]}"List()"
exceptionResult12 = null
hkparams$1 = {[email protected]}"List(type R)"
Così sembra che ci sia una più alta param kinded, tipo R, ma non v'è fornire d valore per quello.
Se effettivamente tornare al al checkKindBounds, si vede che dopo il frammento:
val (arityMismatches, varianceMismatches, stricterBounds) = (
// NOTE: *not* targ.typeSymbol, which normalizes
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
)
il arityMismatches
contiene un elenco tuple, B. Ed ora anche si può vedere che il messaggio di errore è sbagliato:
tipi dedotte di tipo argomenti (MyFoo, MyFoo, Lista [X]) non conformi al tipo attesi dei parametri di tipo (tipo F, tipo R, tipo B). Lista [X] 's parametri di tipo non corrispondono attesi parametri di tipo di B: Lista classe ha un parametro di tipo, ma di tipo B ha ZERO
Infatti se si mette un punto di interruzione alla linea 5859 sul seguente chiamano
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
si può vedere che
tparam = {[email protected]}"type B"
targ = {[email protected]}"List[X]"
Conclusione:
0.123.516,410617 millions
Per qualche motivo, quando si tratta di tipi complessi di tipo superiore come il proprio, l'inferenza del compilatore Scala è limitata. Non so da dove provenga, forse vuoi mandare un bug al team del compilatore
Sto usando scala 2.9.3-20120917-121530-db16547873 –