First of all I would like to put your attention of the fact that having a generic parameter that cannot be inferred is weird, because that does not contain any information about the data contained in the class. If it would, then it would be inferable.

When you do not assign the return type explicitely, a parameter can be inferred. Since infix operator (unless they end with :) in Scala are left associative, in this statement:

val c:Condition[SubSub] = new Condition[Parent] and new Condition[SubSub] and
  new Condition[Sub] and
  new Condition[Parent]

the compiler acts like this :

 ((new Condition[Parent] and new Condition[SubSub]) and
  new Condition[Sub]) and
  new Condition[Parent])

So you end up in the following situation:

  • The first and between Condition[Parent] and Condition[SubSub] returns a type that can't be inferred and that you didn't specify, so it is UnknownType1
  • The second and the same: it is an and between UnknownType1 and a Condition[Sub], returning UnknownType2
  • The third one takes an UnknownType2 and Condition[Parent]. Here the compiler can't check the constraint hold.

Please note that, in the case of the three operands and:

 val b: Condition[SubSub] =
new Condition[Parent] and
  new Condition[SubSub] and
  new Condition[Sub]

The compiler used the type of b to infer the type of the intermediate result (Parent and SubSub) and could check the bounds.

In the failing case, the compiler would need to infer twice the result, and it is not able to do that.

To get back to the initial comment, please also note that in the simple case, if you do not specify the result, the compiler fails as well, and this is normally a sign of poor design of your classes

val e = new Condition[Parent] and new Condition[SubSub]

Related Query

More Query from same tag