Nếu chúng ta nhìn vào trình biên dịch Scala, các nguồn có thể giúp chúng ta hiểu vấn đề là gì. Tôi chưa bao giờ đóng góp cho trình biên dịch Scala, nhưng tôi đã tìm thấy các nguồn rất dễ đọc và tôi đã điều tra về điều đó.
Lớp học chịu trách nhiệm về suy luận kiểu là scala.tools.nsctypechecker.Infer
mà bạn có thể tìm thấy đơn giản bằng cách tìm trong nguồn trình biên dịch Scala cho một phần lỗi của bạn. Bạn sẽ tìm thấy đoạn sau:
/** 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", ", ", ""))
}
Vì vậy, bây giờ, điểm là hiểu tại sao checkKindBounds(tparams, targs, pre, owner)
trả về các lỗi đó.Nếu bạn đi xuống chuỗi gọi phương thức, bạn sẽ thấy rằng các checkKindBounds gọi phương thức khác
val errors = checkKindBounds0(tparams, targs, pre, owner, true)
Bạn sẽ thấy vấn đề được kết nối với kiểm tra giới hạn của loại-kinded cao hơn, tại dòng 5784, bên 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
}
Xét nghiệm này không được thông qua, có vẻ như trong trình gỡ lỗi của tôi:
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)"
Vì vậy, dường như có một cao param kinded, loại R, nhưng không có cung cấp là d giá trị cho điều đó.
Nếu bạn thực sự quay trở lại để checkKindBounds, bạn sẽ thấy rằng sau khi đoạn:
val (arityMismatches, varianceMismatches, stricterBounds) = (
// NOTE: *not* targ.typeSymbol, which normalizes
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
)
các arityMismatches
chứa một danh sách tuple, B. Và bây giờ bạn cũng có thể thấy rằng các thông báo lỗi là sai:
loại tin cậy của các đối số kiểu (MyFoo, MyFoo, Danh sách [X]) không phù hợp với các loại dự kiến của các tham số kiểu (loại F, gõ R, loại B). Danh sách [X] 's tham số kiểu không phù hợp với mong đợi thông số loại B: Danh sách lớp có một số loại, nhưng loại B có ZERO
Trong thực tế, nếu bạn đặt một breakpoint tại dòng 5859 trên sau gọi
checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO)
bạn có thể thấy rằng
tparam = {[email protected]}"type B"
targ = {[email protected]}"List[X]"
Kết luận:
Vì một số lý do, khi giao dịch với các loại phức tạp cao cấp hơn như của bạn, suy luận trình biên dịch Scala bị giới hạn. Tôi không biết nó đến từ đâu, có thể bạn muốn gửi lỗi cho nhóm biên dịch
Tôi đang sử dụng scala 2.9.3-20120917-121530-db16547873 –