Si miramos a el compilador de Scala, las fuentes podrían ayudarnos a entender cuál es el problema. Nunca contribuí con el compilador de Scala, pero encontré las fuentes muy legibles y ya investigué sobre eso.
La clase responsable de la inferencia de tipo es scala.tools.nsctypechecker.Infer
que puede encontrar simplemente buscando en las fuentes del compilador de Scala una parte de su error. Encontrará el siguiente fragmento:
/** 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", ", ", ""))
}
Así que ahora el punto es entender por qué checkKindBounds(tparams, targs, pre, owner)
devuelve esos errores.Si vas por la cadena de llamada a un método, se verá que los checkKindBounds llamar a otro método
val errors = checkKindBounds0(tparams, targs, pre, owner, true)
Vas a ver el problema está conectado a la comprobación de límites del tipo de mayor kinded, en la línea 5784, en el interior 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
}
La prueba no se pasa, parece que en mi depurador:
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)"
Así que parece como que hay un alto parámetro kinded, tipo R, pero sin ofrecer es d valor para eso.
, si intenta ir de nuevo a la de checkKindBounds, se ve que después del fragmento:
val (arityMismatches, varianceMismatches, stricterBounds) = (
// NOTE: *not* targ.typeSymbol, which normalizes
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
)
la arityMismatches
contiene una lista de tuplas, B. Y ahora también se puede ver que el mensaje de error es un error:
tipos inferidos de los argumentos de tipo (myFoo, myFoo, lista [X]) no se ajustan a los tipos esperados de los parámetros de tipo (tipo F, tipo R, tipo B). Lista [X] 's parámetros de tipo no coincide con el esperado parámetros de tipo de B: Lista de clases tiene un parámetro de tipo, pero de tipo B tiene CERO
De hecho, si se pone un punto de interrupción en la línea 5859 en el siguiente llaman
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
se puede ver que
tparam = {[email protected]}"type B"
targ = {[email protected]}"List[X]"
Conclusión:
Por alguna razón, cuando se trata de tipos complejos de alto nivel como el suyo, la inferencia del compilador de Scala es limitada. No sé de dónde viene, quizás quiera enviar un error al equipo del compilador
Estoy usando scala 2.9.3-20120917-121530-db16547873 –