Проблема, , насколько я знаю , заключается в том, что вывод типа работает с использованием алгоритма унификации , который просто попытается удовлетворить ограничения для данные значения. Сначала он попытается доказать, что входные данные v
удовлетворяют типу T#V
, но в этот момент он не имеет никакой информации о T
, поэтому он просто не может выполнить проверку перед проверкой, удовлетворяет ли тип результата условию.
Если вы явно укажете, что T
равно ConcreteA
, то он сможет продолжить.
Однако вы можете заставить его работать, отложив проверку типов аргументов после логического вывода, используя Обобщенные ограничения типов .
def convert[T <: A, V](v: V)(implicit ev: V <:< T#V): T = ???
val converted: ConcreteA = convert(10)
// converted: ConcreteA = ConcreteA(10)
val converted: ConcreteA = convert("hey")
// Compile error: Cannot prove that String <:< T#V.
В этом случае значение v
не имеет никаких ограничений, поэтому компилятор просто связывает V
с типом v
, который уже знает, что это такое. Затем он проверяет тип возвращаемого значения T
, который, как он знает, должен быть ConcreteA
, который удовлетворяет условию, что он должен быть подтипом A
, таким образом, он проходит.
После решения логического вывода компилятор пытается решить имплики . В этом случае ему необходимо получить (доказать) , что V <:< T#V
, что в первом случае работает, но во втором не получается.