Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Table & Row data classes covariant #342

Merged
merged 1 commit into from
May 24, 2018

Conversation

xenomachina
Copy link
Contributor

Hello.

I ran into a problem where I was doing something similar to:

abstract class Shape
object Circle : Shape() {}
object Square : Shape() {}

...

val table6 = table(
    headers("a", "b", "c"),
    row("foo", 5, Circle),
    row("bar", 42, Square)
)

I was getting loads of error messages like:

Error:(21, 16) Kotlin: None of the following functions can be called with the arguments supplied: 
public fun <A> table(headers: Headers1, vararg rows: Row1<???>): Table1<???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J> table(headers: Headers10, vararg rows: Row10<???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table10<???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K> table(headers: Headers11, vararg rows: Row11<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table11<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L> table(headers: Headers12, vararg rows: Row12<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table12<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M> table(headers: Headers13, vararg rows: Row13<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table13<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N> table(headers: Headers14, vararg rows: Row14<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table14<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> table(headers: Headers15, vararg rows: Row15<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table15<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P> table(headers: Headers16, vararg rows: Row16<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table16<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q> table(headers: Headers17, vararg rows: Row17<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table17<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R> table(headers: Headers18, vararg rows: Row18<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table18<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S> table(headers: Headers19, vararg rows: Row19<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table19<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B> table(headers: Headers2, vararg rows: Row2<String, ???>): Table2<String, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T> table(headers: Headers20, vararg rows: Row20<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table20<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U> table(headers: Headers21, vararg rows: Row21<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table21<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V> table(headers: Headers22, vararg rows: Row22<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???>): Table22<???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C> table(headers: Headers3, vararg rows: Row3<???, ???, ???>): Table3<???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D> table(headers: Headers4, vararg rows: Row4<???, ???, ???, ???>): Table4<???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E> table(headers: Headers5, vararg rows: Row5<???, ???, ???, ???, ???>): Table5<???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F> table(headers: Headers6, vararg rows: Row6<???, ???, ???, ???, ???, ???>): Table6<???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G> table(headers: Headers7, vararg rows: Row7<???, ???, ???, ???, ???, ???, ???>): Table7<???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H> table(headers: Headers8, vararg rows: Row8<???, ???, ???, ???, ???, ???, ???, ???>): Table8<???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties
public fun <A, B, C, D, E, F, G, H, I> table(headers: Headers9, vararg rows: Row9<???, ???, ???, ???, ???, ???, ???, ???, ???>): Table9<???, ???, ???, ???, ???, ???, ???, ???, ???> defined in io.kotlintest.properties

A workaround is to cast to a common type:

val table6 = table(
    headers("a", "b", "c"),
    row("foo", 5, Circle as Shape),
    row("bar", 42, Square as Shape)
)

or to specify type parameters explicitly:

val table6 = table(
    headers("a", "b", "c"),
    row<String, Int, Shape>("foo", 5, Circle),
    row<String, Int, Shape>("bar", 42, Square)
)

But changing the Table* and Row* classes to be covariant makes it so Kotlin
is able to treat a Row2<String, Circle> as a Row<String, Shape>, and so
this can compile without having to use a workaround.

The test I've included is a bit weird, as it doesn't do anything at runtime,
because this code change doesn't actually change any runtime behavior. The test
won't compile without this change, though, so it does verify that the fix has
happened, and its existence helps makes sure the variance continues to exist.

@sksamuel
Copy link
Member

That's a lot of copy n pasting the word out :)
Thanks for the PR. 👍

@sksamuel sksamuel merged commit 3cb912a into kotest:master May 24, 2018
@xenomachina
Copy link
Contributor Author

This is one of those times when it was easier to do the edit in Vim than in IntelliJ. 😄

@xenomachina xenomachina deleted the fix-variance branch May 24, 2018 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants