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

Feature request: Type logic and variance #10

Open
Jolanrensen opened this issue Jun 6, 2024 · 1 comment
Open

Feature request: Type logic and variance #10

Jolanrensen opened this issue Jun 6, 2024 · 1 comment

Comments

@Jolanrensen
Copy link

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>>
}
@romainbsl
Copy link
Member

Thank you for reaching out.

We have started considering your request. However, this may be challenging due to the non-JVM platform, which has limited APIs compared to JVM.

Currently, this library fulfills its original purpose as it is the core of our dependency injection library, Kodein.

We need to evaluate how the typeOf function has evolved to determine if new capabilities have been added. Unfortunately, we don't have the bandwidth at the moment. Feel free to investigate if you have the time.

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

No branches or pull requests

2 participants