Skip to content

Feature request: Type logic and variance #10

@Jolanrensen

Description

@Jolanrensen

First of all, great job :) A multiplatform reflection library is a great addition to the ecosystem :)

We're looking at migrating a library to multiplatform in the future, but we rely heavily on reflection and type logic, so I'm curious to see how far Kaverit can help us.

I do have a couple suggestions and concerns.

Variance and * notations:

I noticed TypeToken.getGenericParameters() fills in * parameters of generics with Any no matter the variance or supertype:

generic<List<*>>().getGenericParameters()[0]

is given as kotlin.Any. In this case, * means Any?, but I see you don't support nullability on purpose, so that's fine.

However, for

interface Test<T : Number>
generic<Test<*>>().getGenericParameters()[0]

it returns kotlin.Any too. I'd expect there to be a way to know that * means Number here.

Finally,

generic<Comparable<*>>().getGenericParameters()[0]

also gives kotlin.Any, which, according to the docs should be kotlin.Nothing. This is because the variance of type T is in in Comparable<in T>.

Combining types

Aside from that, I'd also be interested in a way to "add" multiple types together and do some logic, finding the lowest common parent between two types.
Something like:

fun sharedTypes(a: TypeToken<*>, b: TypeToken<*>): List<TypeToken<*>> {
    val aTypes = listOf(a) + a.getSuper()
    val bTypes = listOf(b) + b.getSuper()
    return (aTypes intersect bTypes).toList() + TypeToken.Any
}

fun lowestCommonType(a: TypeToken<*>, b: TypeToken<*>): TypeToken<*> =
    sharedTypes(a, b).first()

lowestCommonType(generic<Int>(), generic<Double>()) == generic<Number>()

but a bit more efficient maybe, and it should be able to calculate lowestCommonType(generic<List<Int>>(), generic<List<Double>>()) correctly. This might also require some variance/bound checks on generics. Specifically, I'd be interested in calculating the combinations of types such as the highlighting of the IDE can do like this:

interface A : Comparable<Double>
interface B : Comparable<Int>
interface C : Comparable<Number>

interface D : List<Double>
interface E : List<Number>

fun function(a: A, b: B, c: C, d: D, e: E) {
    val list1 = listOf(a, c) // inferred as List<Comparable<Double>>
    val list2 = listOf(a, b) // inferred as List<Comparable<Nothing>>
    val list3 = listOf(d, e) // inferred as List<List<Number>>
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions