That isn’t how type inference in Scala works; your mental model is too simple. Types aren’t inferred in a vacuum, they’re inferred w/r/t some expected type bounds, and those bounds come from context.
Consider the following interaction:
scala 2.13.1> trait SomeTrait
defined trait SomeTrait
scala 2.13.1> val a: SomeTrait = Option("foo").getOrElse("bar")
^
error: type mismatch;
found : String("bar")
required: SomeTrait
Look at the error closely and note where the caret is pointing. It isn’t saying the result of getOrElse
is the wrong type, it’s saying "bar"
is the wrong type! What’s happening here? Well, when the getOrElse
call is being typechecked, the expected type of the call is SomeTrait
— that’s coming from the left-hand-side. The only way that’s going to work is if B
is some type compatible with SomeTrait
— perhaps SomeTrait
itself. So the typechecker says to itself, “B now has an upper bound of SomeTrait”. With that information in mind, tries to type check the argument to getOrElse
. That argument doesn’t conform to B
's bounds, hence the error above.
I worked through this simpler example because it shows what I mean by an “expected type” guiding type inference, and proves that it’s happening, because if it weren’t, the error would be different.
OK, that’s enough for one post. I haven’t actually worked out where Object
is coming from in your full example. I may have accidentally given the impression that I have the answer all worked out already. But I don’t, I’m exploring this with you and Luis a piece at time.