Summary
If I pass a literal expression as an argument to a function, this should not coincide with the first evaluation of the same expression of the literal expression, and then bind the variable to the value returned from that evaluation, and then pass the variable name as the same argument for the same function ? And if this literal expression returns the wrong type for the function parameter, then skipping the step of assigning the value to the intermediate variable, the type of which Scala deduces from the return value of the expression, should not skip this incompatible function type where the type-mismatch error occurred before it, right? But is this not shown in the following example?
Example
Here I am trying to get a parameter of a function like Array[Super] to accept the value of Array[Sub] . Declare the following in Scala repl. Pay attention to the type of function of one parameter:
class Super class Sub extends Super def wantsSuperArray(a: Array[Super]) { println(a.size) }
Then build an instance of Sub
scala> val s = new Sub s: Sub = Sub@2c9fa2fb
Create an Array[Sub] :
scala> val subArray = Array(s) subArray: Array[Sub] = Array( Sub@2c9fa2fb )
It will be noted below that a generic Array is type-invariant and that Array[Sub] not Array[Super] although a Sub is Super :
scala> wantsSuperArray(subArray) <console>:13: error: type mismatch; found : Array[Sub] required: Array[Super] Note: Sub <: Super, but class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ <: Super`. (SLS 3.2.10) wantsSuperArray(subArray) ^
There are no surprises yet.
Amazing observation
We just saw that wantsSuperArray() will not be used as the argument type of a Array[Sub] . So why does the following not generate the same type mismatch error message as above?
scala> wantsSuperArray(Array(new Sub)) 1
Similarly, why does this not cause errors?
scala> wantsSuperArray(Array(s)) 1
Keep in mind that the compiler sequentially considers three options with the help of repl, namely it refuses to compile and produce the same type mismatch error for the first and compile the second and third.
Additional Information
If we explicitly parameterize Array as follows, then an error message appears:
scala> wantsSuperArray(Array[Sub](new Sub)) <console>:11: error: type mismatch; found : Array[Sub] required: Array[Super] Note: Sub <: Super, but class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ <: Super`. (SLS 3.2.10) wantsSuperArray(Array[Sub](new Sub)) ^
So it’s obvious that if there is no intermediate variable, Scala can see what type wantsSuperArray wants and does some kind of conversion, possibly dropping from Array[Sub] to Array[Super] . However, this is similar to getting it, because I still think that choosing to use or not use the intermediate variable should not cause such a difference in the program operation, and this particular situation seems to perform the casting instead of raising the error to the programmer would expect based on the immutability of a typical parameter of type Array .
Questions
If I believe that when calling wantsSuperArray() as defined above, passing a literal expression should be the same as passing a variable name containing the value obtained by evaluating the same expression as shown above, what am I misunderstanding?
How can I improve my understanding of what I am observing and complaining here?
Where in the Scala documentation can I read about the phenomenon that I am observing here to be able to understand this and never be surprised at it again?