Ответ 1
Если мы посмотрим на компилятор Scala, источники могут помочь нам понять, в чем проблема. Я никогда не участвовал в компиляторе Scala, но нашел исходники очень читаемыми, и я уже изучил их.
Класс, ответственный за вывод типа scala.tools.nsctypechecker.Infer
, который вы можете найти, просто просмотрев в источниках компилятора Scala часть части вашей ошибки. Вы узнаете следующий фрагмент:
/** 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", ", ", ""))
}
Итак, теперь понятно, почему checkKindBounds(tparams, targs, pre, owner)
возвращает эти ошибки. Если вы опустите цепочку вызовов метода, вы увидите, что checkKindBounds вызывает другой метод
val errors = checkKindBounds0(tparams, targs, pre, owner, true)
Вы увидите, что проблема связана с проверкой границ более высокого типа в строке 5784 внутри 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
}
Тест не передан, кажется, что в моем отладчике:
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)"
Таким образом, похоже, что существует один более высокий соразмерный параметр, тип R, но для него не предусмотрено значение.
Если вы действительно вернетесь к checkKindBounds, вы увидите, что после фрагмента:
val (arityMismatches, varianceMismatches, stricterBounds) = (
// NOTE: *not* targ.typeSymbol, which normalizes
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
)
arityMismatches
содержит список кортежей, B. И теперь вы также можете увидеть, что сообщение об ошибке неверно:
выведенные типы аргументов типа (MyFoo, MyFoo, List [X]) не соответствуют ожидаемым типам параметров типа (тип F, тип R, тип B). Параметры списка [X] не соответствуют ожидаемому типу B parameters: class List имеет один параметр типа, но тип B имеет ZERO
Фактически, если вы поместите точку останова на строку 5859 при следующем вызове
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
вы можете видеть, что
tparam = {[email protected]}"type B"
targ = {[email protected]}"List[X]"
Заключение:
По какой-то причине при работе со сложными типами более высокого класса, такими как ваш, вывод Scala компилятора ограничен. Я не знаю, откуда она взялась, возможно, вы хотите отправить ошибку команде компилятора.