Hi,
I’ve written the following example:
https://try.kotlinlang.org/#/UserProjects/rtfqr2e5ucevqnv7tlac56d6ah/7ukm06j2otcrhss306ghnrmnm4
(Running with JavaScript gives a better output because it concats the array content)
The first function call to containsAll
outputs the result that I would expect, that “Hello” and “World” are both within the Iterable.
However, the second function call should, in my opinion, not be allowed by the compiler.
The type of T
should in the second call also be infered to String
and therefore arrayOf
without spreading should not be allowed.
If I compile it on the JVM with the following changes:
inline fun <reified T, reified I : Iterable<T>> I.containsAll(vararg items: T) {
println("I is Iterable<"+ I::class.typeParameters.joinToString() +">")
println("T is " + T::class.simpleName)
items.forEach {
println("Iterable contains $it: ${this.contains(it)}")
}
}
fun main(args: Array<String>) {
val iterable: Iterable<String> = listOf("Hello", "World")
iterable.containsAll("Hello", "World")
println()
iterable.containsAll(arrayOf("Hello", "World"))
}
it prints
I is Iterable<out T>
T is String
Iterable contains Hello: true
Iterable contains World: true
I is Iterable<out T>
T is Serializable
Iterable contains [Ljava.lang.String;@11e21d0e: false
Process finished with exit code 0
Is this expected behavior?
If Array
does implement Serializable
, it kind of makes sense but still feels strange.
Changing the example to:
data class MyString(val str: String)
inline fun <reified T, reified I : Iterable<T>> I.containsAll(vararg items: T) {
println("I is Iterable<"+ I::class.typeParameters.joinToString() +">")
println("T is " + T::class.simpleName)
items.forEach {
println("Iterable contains $it: ${this.contains(it)}")
}
}
fun main(args: Array<String>) {
val iterable: Iterable<MyString> = listOf(MyString("Hello"), MyString("World"))
iterable.containsAll(MyString("Hello"), MyString("World"))
println()
iterable.containsAll(arrayOf(MyString("Hello"), MyString("World")))
}
it just infers Any
:
I is Iterable<out T>
T is MyString
Iterable contains MyString(str=Hello): true
Iterable contains MyString(str=World): true
I is Iterable<out T>
T is Any
Iterable contains [MyString;@11e21d0e: false
Is this expected behavior? It feels kind of dangerous to me :-/