Коротко: ваше сообщение об ошибке должно быть просто
error: type mismatch
found: Ordering[Int]
required: Int.
Причина в том, что в Ordered[A]
сравнение выполняется с A
, а не с другими порядками
def <(that: A): Boolean
Это должно быть o1 < 2
, а не o1 < o2
.(конечно, 1 < 2
тоже работает, но я ожидаю, что ваш код - просто упрощенная версия чего-то еще)
Однако, прежде чем компилятор сообщит об этой простой ошибке, он должен искать, может ли какой-то неявный в области видимости исправитьэта проблема.Он может преобразовать Ordering[Int]
o2
в Int
(не может) или Ordering[Int]
o1
во что-то, что имеет метод def <(Ordered[Int])
, например Ordered[Ordered[Int]]
.И бывает, что он должен остановить поиск, потому что кажется, что он может продолжаться бесконечно в виде цикла.Правило дано в спецификации, с.От 107 до 109 (спецификация для версии 2.9).Однако правило остановки поиска является пессимистичным, и, возможно, оно отбрасывает строку поиска, которая могла быть успешной, поэтому компилятор считает, что должен сообщить об этом.Хотя на самом деле большую часть времени, как здесь, цикл был должным образом отброшен, и никакого решения не существовало.Это то, что делает неожиданное сообщение об ошибке.Я думаю, что более простая ошибка должна быть сообщена и более заметна.
Позвольте мне дать некоторые ограниченные объяснения того, почему в неявном поиске может быть цикл.Может быть
implicit def f(implicit a: A): B
, что означает, что если у вас есть неявное A
, у вас также есть неявное B
.Так что получается график между типами: A
обеспечивает B
.Это сложнее, чем это, на самом деле это гиперграф: implcit def f(implicit a: A, implicit b: B): C
: A
и B
обеспечивает C
.
При использовании дженериков у вас есть бесконечное число типов и бесконечный (гипер) граф, еще более усложненный подтипом (если вам нужен A
, подойдет любой подтип A
. Добавьтеправило подтипов, подразумеваемое ковариацией / контравариантностью)
График может содержать цикл: для получения A
вы можете просто указать B
;чтобы получить B
, вы можете просто предоставить C
;чтобы получить C
, вы можете просто предоставить A
.Это означает, что если вы предоставите A
, вы получите A
, что бесполезно, и эту строку поиска нужно отбросить.В данном случае это не проблема: это реальный цикл, и нет риска обойти возможное решение, отбросив его.
Но это может быть сложнее.Поскольку граф бесконечен, поиск может быть бесконечным без точного зацикливания.Если у вас есть
implicit def[A](x: X[X[A]]): X[A]
, то если вы ищете X[Int]
, вы можете вместо этого искать X[X[Int]]
, но затем, с тем же правилом, вы ищите X[X[X[Int]]]
и так далее.Это не точно цикл, но компилятор не обрабатывает эти строки и называет их расходящимися.За исключением того, что может быть неявное X[X[X...X[Int]]]]]
в неявном объеме где-то, что сделает его успешным.Вот почему компилятор сообщает, что эта линия исследования была отброшена.