This works : ```fun <T, M : MutableCollection&l...
# announcements
s
This works :
Copy code
fun <T, M : MutableCollection<T>> Collection<T>.partitionTo(left: M, right: M, predicate: (T) -> Boolean): Pair<Collection<T>, Collection<T>> {
    forEach {
        if (predicate(it)) left += it else right += it
    }
    return Pair(left, right)
}
so as this:
Copy code
fun <T, C : Collection<T>, M : MutableCollection<T>> C.partitionTo(left: M, right: M, predicate: (T) -> Boolean): Pair<Collection<T>, Collection<T>> {
    forEach {
        if (predicate(it)) left += it else right += it
    }
    return Pair(left, right)
}
This doesn’t compile… why?
Copy code
fun <T, C : Collection<T>, M : MutableCollection<T>> C.partitionTo(left: M, right: M, predicate: (T) -> Boolean): Pair<C, C> {
    forEach {
        if (predicate(it)) left += it else right += it
    }
    return Pair(left, right)
}
when you cast it, then i works then but it’s unsafe cast..
Copy code
fun <T, C : Collection<T>, M : MutableCollection<T>> C.partitionTo(left: M, right: M, predicate: (T) -> Boolean): Pair<C, C> {
    forEach {
        if (predicate(it)) left += it else right += it
    }
    return Pair(left as C, right as C)
}
Why can’t typesystem figure out that M is covariant towards C ?
s
M and C are different type parameters and are not related to each other. Same reason as to why
fun <M, C> foo(m: M): C = m
doesn’t compile: even though they both have
Any?
as an upper bound, they can be different types and cannot be assigned to one another.
1
👍 1
y
Exactly as Svyatoslav said. However, you can make your example work by using a type parameter bounded by both MutableCollection and C:
Copy code
@Suppress("BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER")
fun <T, C : Collection<T>, M> C.partitionTo(left: M, right: M, predicate: (T) -> Boolean): Pair<C, C> where M  : MutableCollection<T>, M : C {
    forEach {
        if (predicate(it)) left += it else right += it
    }
    return Pair(left, right)
}
Please note that this won't be callable from Java because it doesn't understand that signature, that's why that
@Suppress
is needed
s
I would not recommend suppressing compiler errors 🙂 There are no guarantees that they work as you expected or will continue to do work in the future.