Add tests for inferring self types from Java
This commit is contained in:
-1
@@ -2,7 +2,6 @@
|
||||
|
||||
class Builder<B : Builder<B>> {
|
||||
fun <T : B> test(): T = TODO()
|
||||
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
|
||||
class Builder<B : Builder<B>> {
|
||||
fun <T : B> test(): T = TODO()
|
||||
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
|
||||
+28
-3
@@ -1,5 +1,14 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaBuilder.java
|
||||
public class JavaBuilder<B extends JavaBuilder<B>> {
|
||||
<T extends B> T test() {
|
||||
return null;
|
||||
}
|
||||
void foo() { }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Builder<B : Builder<B>> {
|
||||
fun <T : B> test(): T = TODO()
|
||||
|
||||
@@ -7,7 +16,7 @@ class Builder<B : Builder<B>> {
|
||||
}
|
||||
|
||||
fun testStar(builder: Builder<*>) {
|
||||
builder.test()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Builder<*>")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
@@ -15,9 +24,25 @@ fun testStar(builder: Builder<*>) {
|
||||
}
|
||||
|
||||
fun <K : Builder<K>> testTypeParam(builder: Builder<K>) {
|
||||
builder.test()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun testStarJava(builder: JavaBuilder<*>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Builder<*>")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
|
||||
fun <K : JavaBuilder<K>> testTypeParamJava(builder: JavaBuilder<K>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("K")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
|
||||
+25
@@ -1,5 +1,14 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaBuilder.java
|
||||
public class JavaBuilder<B extends JavaBuilder<B>> {
|
||||
<T extends B> T test() {
|
||||
return null;
|
||||
}
|
||||
void foo() { }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
class Builder<B : Builder<B>> {
|
||||
fun <T : B> test(): T = TODO()
|
||||
|
||||
@@ -21,3 +30,19 @@ fun <K : Builder<K>> testTypeParam(builder: Builder<K>) {
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
|
||||
fun testStarJava(builder: JavaBuilder<*>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(JavaBuilder<*>..JavaBuilder<*>?)")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
|
||||
fun <K : JavaBuilder<K>> testTypeParamJava(builder: JavaBuilder<K>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(K..K?)")!>builder.test()<!>
|
||||
|
||||
builder
|
||||
.test()
|
||||
.foo()
|
||||
}
|
||||
|
||||
+11
@@ -1,7 +1,9 @@
|
||||
package
|
||||
|
||||
public fun testStar(/*0*/ builder: Builder<*>): kotlin.Unit
|
||||
public fun testStarJava(/*0*/ builder: JavaBuilder<*>): kotlin.Unit
|
||||
public fun </*0*/ K : Builder<K>> testTypeParam(/*0*/ builder: Builder<K>): kotlin.Unit
|
||||
public fun </*0*/ K : JavaBuilder<K>> testTypeParamJava(/*0*/ builder: JavaBuilder<K>): kotlin.Unit
|
||||
|
||||
public final class Builder</*0*/ B : Builder<B>> {
|
||||
public constructor Builder</*0*/ B : Builder<B>>()
|
||||
@@ -12,3 +14,12 @@ public final class Builder</*0*/ B : Builder<B>> {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class JavaBuilder</*0*/ B : JavaBuilder<B!>!> {
|
||||
public constructor JavaBuilder</*0*/ B : JavaBuilder<B!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public/*package*/ open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public/*package*/ open fun </*0*/ T : B!> test(): T!
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
|
||||
+15
-2
@@ -1,10 +1,23 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaBodySpec.java
|
||||
public interface JavaBodySpec<B, S extends JavaBodySpec<B, S>> {
|
||||
default <T extends S> T isEqualTo(B expected) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
interface BodySpec<B, S : BodySpec<B, S>> {
|
||||
fun <T : S> isEqualTo(expected: B): T
|
||||
}
|
||||
|
||||
fun test(b: BodySpec<String, *>) {
|
||||
val x = b.isEqualTo("")
|
||||
x
|
||||
}
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("BodySpec<*, *>")!>x<!>
|
||||
}
|
||||
|
||||
fun testJava(b: JavaBodySpec<String, *>) {
|
||||
val x = b.isEqualTo("")
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("BodySpec<*, *>")!>x<!>
|
||||
}
|
||||
|
||||
+13
@@ -1,5 +1,13 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaBodySpec.java
|
||||
public interface JavaBodySpec<B, S extends JavaBodySpec<B, S>> {
|
||||
default <T extends S> T isEqualTo(B expected) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
interface BodySpec<B, S : BodySpec<B, S>> {
|
||||
fun <T : S> isEqualTo(expected: B): T
|
||||
}
|
||||
@@ -8,3 +16,8 @@ fun test(b: BodySpec<String, *>) {
|
||||
val x = b.isEqualTo("")
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("BodySpec<*, *>")!>x<!>
|
||||
}
|
||||
|
||||
fun testJava(b: JavaBodySpec<String, *>) {
|
||||
val x = b.isEqualTo("")
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(JavaBodySpec<*, *>..JavaBodySpec<*, *>?)")!>x<!>
|
||||
}
|
||||
|
||||
+25
@@ -1,5 +1,23 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaWriterAppender.java
|
||||
public class JavaWriterAppender {
|
||||
interface Builder2<K extends Builder2<K>> {}
|
||||
|
||||
class Builder1<B extends Builder1<B>> {
|
||||
B asBuilder() { return null; }
|
||||
}
|
||||
|
||||
<B extends Builder1<B>> B newBuilder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
<B extends Builder1<B> & Builder2<B>> B intersectTwoSelfTypes() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun test() {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<*>")!>WriterAppender.newBuilder()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<out WriterAppender.Builder1<*>>")!>WriterAppender.Builder1()<!>
|
||||
@@ -7,6 +25,13 @@ fun test() {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("{Builder1<*> & Builder2<*>}")!>WriterAppender.intersectTwoSelfTypes()<!>
|
||||
}
|
||||
|
||||
fun testJava(appender: JavaWriterAppender) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<*>")!>appender.newBuilder()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<out WriterAppender.Builder1<*>>")!>appender.Builder1()<!>
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("{Builder1<*> & Builder2<*>}")!>appender.intersectTwoSelfTypes()<!>
|
||||
}
|
||||
|
||||
object WriterAppender {
|
||||
interface Builder2<K : Builder2<K>>
|
||||
|
||||
|
||||
+25
@@ -1,5 +1,23 @@
|
||||
// !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes
|
||||
|
||||
// FILE: JavaWriterAppender.java
|
||||
public class JavaWriterAppender {
|
||||
interface Builder2<K extends Builder2<K>> {}
|
||||
|
||||
class Builder1<B extends Builder1<B>> {
|
||||
B asBuilder() { return null; }
|
||||
}
|
||||
|
||||
<B extends Builder1<B>> B newBuilder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
<B extends Builder1<B> & Builder2<B>> B intersectTwoSelfTypes() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun test() {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<*>")!>WriterAppender.newBuilder()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<out WriterAppender.Builder1<*>>")!>WriterAppender.Builder1()<!>
|
||||
@@ -7,6 +25,13 @@ fun test() {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("{Builder1<*> & Builder2<*>}")!>WriterAppender.intersectTwoSelfTypes()<!>
|
||||
}
|
||||
|
||||
fun testJava(appender: JavaWriterAppender) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(JavaWriterAppender.Builder1<*>..JavaWriterAppender.Builder1<*>?)")!>appender.newBuilder()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("JavaWriterAppender.Builder1<out (JavaWriterAppender.Builder1<*>..JavaWriterAppender.Builder1<*>?)>")!>appender.Builder1()<!>
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("({Builder1<*> & Builder2<*>}..{Builder1<*>? & Builder2<*>?}?)")!>appender.intersectTwoSelfTypes()<!>
|
||||
}
|
||||
|
||||
object WriterAppender {
|
||||
interface Builder2<K : Builder2<K>>
|
||||
|
||||
|
||||
+24
@@ -1,6 +1,30 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
public fun testJava(/*0*/ appender: JavaWriterAppender): kotlin.Unit
|
||||
|
||||
public open class JavaWriterAppender {
|
||||
public constructor JavaWriterAppender()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public/*package*/ open fun </*0*/ B : JavaWriterAppender.Builder1<B!>!> intersectTwoSelfTypes(): B! where B : JavaWriterAppender.Builder2<B!>!
|
||||
public/*package*/ open fun </*0*/ B : JavaWriterAppender.Builder1<B!>!> newBuilder(): B!
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public/*package*/ open inner class Builder1</*0*/ B : JavaWriterAppender.Builder1<B!>!> {
|
||||
public/*package*/ constructor Builder1</*0*/ B : JavaWriterAppender.Builder1<B!>!>()
|
||||
public/*package*/ open fun asBuilder(): B!
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public/*package*/ interface Builder2</*0*/ K : JavaWriterAppender.Builder2<K!>!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public object WriterAppender {
|
||||
private constructor WriterAppender()
|
||||
|
||||
@@ -546,13 +546,15 @@ object AbstractTypeChecker {
|
||||
targetType: KotlinTypeMarker
|
||||
): TypeParameterMarker? {
|
||||
for (i in 0 until baseType.argumentsCount()) {
|
||||
val typeArgument = baseType.getArgument(i).takeIf { !it.isStarProjection() } ?: continue
|
||||
val typeArgument = baseType.getArgument(i).takeIf { !it.isStarProjection() }?.getType() ?: continue
|
||||
val areBothTypesCaptured =
|
||||
typeArgument.lowerBoundIfFlexible().isCapturedType() && targetType.lowerBoundIfFlexible().isCapturedType()
|
||||
|
||||
if (typeArgument.getType() == targetType) {
|
||||
if (typeArgument == targetType || (areBothTypesCaptured && typeArgument.typeConstructor() == targetType.typeConstructor())) {
|
||||
return baseType.typeConstructor().getParameter(i)
|
||||
}
|
||||
|
||||
getTypeParameterForArgumentInBaseIfItEqualToTarget(typeArgument.getType(), targetType)?.let { return it }
|
||||
getTypeParameterForArgumentInBaseIfItEqualToTarget(typeArgument, targetType)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user