Its all about generics notations principles and concepts. I am taking forward from example posted by ijrandom. Let us take the first scenario where U and V implements only X. For the time being we are not assigning method output to a reference variable. We have called the union method as given below:
union(integers, doubles);
We know that for generics the actual parameter type is determined by the type you specify while calling method, so in this case the return type for method will be Set of X, just move cursor over the method call you will see how java compiler has determined actual parameter type at compile time.
In our second scenario we once again call the method union:
union(integers, doubles);//Note we have not yet assigned the returned value to a variable.
Move cursor over method call, you will notice that return type for method changes to Set of unknown extends X, thus here the compiler is not able to resolve completely the actual type as U and V implements both X and Y and X is not Y. Hence as soon as you assign value to variable, error is produced as compiler is still not able to identify the actual type. In such scenario you need to tell compiler which actual type to use.