Skip to content

Commit

Permalink
recursively substitute functions for compute asMemberOf
Browse files Browse the repository at this point in the history
  • Loading branch information
neetopia committed Jun 20, 2024
1 parent b9db1a4 commit b7e977c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -835,8 +835,15 @@ class ResolverAAImpl(
// recursively substitute to ensure transitive substitution works.
// should fix in upstream as well.
var result = resolved.type
var cnt = 0
while (it.substitute(result) != result) {
if (cnt > 100) {
throw IllegalStateException(
"Potential infinite loop in type substitution for computeAsMemberOf"
)
}
result = it.substitute(result)
cnt += 1
}
KSTypeImpl.getCached(result)
}
Expand Down Expand Up @@ -869,10 +876,32 @@ class ResolverAAImpl(
)
}
analyze {
// TODO: recursive substitution does not solve fix point problem for signatures, probably needs fix in upstream.
buildSubstitutor {
fillInDeepSubstitutor(containing.type, this@buildSubstitutor)
}.let { (function as KSFunctionDeclarationImpl).ktFunctionSymbol.substitute(it) }.let {
}.let {
// recursively substitute to ensure transitive substitution works.
// should fix in upstream as well.
// for functions we need to test both returnType and value parameters converges.
var funcToSub = (function as KSFunctionDeclarationImpl).ktFunctionSymbol.substitute(it)
var next = funcToSub.substitute(it)
var cnt = 0
while (
funcToSub.returnType != next.returnType ||
funcToSub.valueParameters.zip(next.valueParameters)
.any { it.first.returnType != it.second.returnType } ||
funcToSub.receiverType != next.receiverType
) {
if (cnt > 100) {
throw IllegalStateException(
"Potential infinite loop in type substitution for computeAsMemberOf"
)
}
funcToSub = next
next = funcToSub.substitute(it)
cnt += 1
}
funcToSub
}.let {
KSFunctionImpl(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ class AsMemberOfProcessor : AbstractTestProcessor() {
results.add(getX.asMemberOf(javaImpl.asStarProjectedType()).toSignature())
results.add(getY.asMemberOf(javaImpl.asStarProjectedType()).toSignature())
results.add(setY.asMemberOf(javaImpl.asStarProjectedType()).toSignature())

resolver.getClassDeclarationByName("Baz")!!.let { cls ->
cls.getDeclaredFunctions().single { it.simpleName.asString() == "method1" }.let { f ->
val usage = resolver.getClassDeclarationByName("Usage")!!.asType(emptyList())
results.add(f.asMemberOf(usage).returnType!!.toSignature())
}
}
return emptyList()
}

Expand Down
11 changes: 11 additions & 0 deletions test-utils/testData/api/asMemberOf.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
// () -> kotlin.Int!!
// () -> kotlin.Int!!
// (kotlin.Int!!) -> kotlin.Unit!!
// Baz!!<kotlin.Long!!, kotlin.Number!!>
// END
// FILE: Input.kt
open class Base<BaseTypeArg1, BaseTypeArg2> {
Expand Down Expand Up @@ -156,6 +157,16 @@ interface KotlinInterface {
var y:Int
}

interface Usage : Foo<Long, Integer> {
fun foo(param: Foo<Double, Integer>): Foo<String, Integer>
}
interface Foo<V1, V2: Integer> : Bar<Baz<V1, Number>, V2> {}
interface Bar<U1, U2: Integer> : Baz<U1, U2> {}
interface Baz<T1, T2: Number> {
fun method1(): T1
fun method2(): T2
}

// FILE: JavaInput.java
class JavaBase<BaseTypeArg1, BaseTypeArg2> {
int intType;
Expand Down

0 comments on commit b7e977c

Please sign in to comment.