В последних случаях компилятор предполагает, что вы хотите, чтобы это работало, и на самом деле говорит
p(Crate( (new Apple): Fruit ))
, что совершенно нормально.Это так же, как если бы вы делали это вручную
val f: Fruit = new Apple // totally fine
p(Crate(f)) // Also totally fine
Это лишь малая часть огромного волшебства, которое применяет компилятор, чтобы попытаться выяснить, что вы имеете в виду с вашими типами, не заставляя вас печатать все это.