[NI] Implement algorithm for completion mode selection
Current selection of completion mode for call is not always correct in case of full mode, and sometimes too conservative in case of partial mode. Updated algorithm checks constraints wrt position of type variables in return type and in other related constraints. Full completion happens if proper constraint requirements are satisfied for variables.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
interface Bound
|
||||
class Cls : Bound
|
||||
|
||||
class Inv<T>(val prop: T)
|
||||
class In<in I>(param: I)
|
||||
class InB<in I : Bound>(param: I)
|
||||
class Out<out O>(val prop: O)
|
||||
|
||||
fun <K> id(arg: K): K = arg
|
||||
fun <W> makeInv(arg: W): Inv<W> = TODO()
|
||||
fun <O> wrapOut(arg: O): Inv<out O> = TODO()
|
||||
fun <I> wrapIn(arg: I): Inv<in I> = TODO()
|
||||
|
||||
fun test1(cls: Cls) {
|
||||
id(
|
||||
Inv(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test2(cls: Cls) {
|
||||
id<Inv<Bound>>(
|
||||
Inv(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test3(cls: Cls) {
|
||||
id<Out<Bound>>(
|
||||
Out(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test4(cls: Cls) {
|
||||
id(
|
||||
Out(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test5(cls: Cls) {
|
||||
id(
|
||||
In(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test6(cls: Cls) {
|
||||
id<In<Bound>>(
|
||||
In(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test7(cls: Cls) {
|
||||
id(
|
||||
wrapOut(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test8(cls: Cls) {
|
||||
// TODO
|
||||
id(
|
||||
wrapIn(cls)
|
||||
)
|
||||
}
|
||||
|
||||
fun test9(cls: Cls) {
|
||||
id(
|
||||
InB(cls)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
interface Bound
|
||||
class Cls : Bound
|
||||
|
||||
class Inv<T>(val prop: T)
|
||||
class In<in I>(param: I)
|
||||
class InB<in I : Bound>(param: I)
|
||||
class Out<out O>(val prop: O)
|
||||
|
||||
fun <K> id(arg: K): K = arg
|
||||
fun <W> makeInv(arg: W): Inv<W> = TODO()
|
||||
fun <O> wrapOut(arg: O): Inv<out O> = TODO()
|
||||
fun <I> wrapIn(arg: I): Inv<in I> = TODO()
|
||||
|
||||
fun test1(cls: Cls) {
|
||||
id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<Cls>")!>Inv(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test2(cls: Cls) {
|
||||
id<Inv<Bound>>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<Bound>")!>Inv(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test3(cls: Cls) {
|
||||
id<Out<Bound>>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Out<Cls>")!>Out(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test4(cls: Cls) {
|
||||
id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Out<Cls>")!>Out(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test5(cls: Cls) {
|
||||
id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("In<Cls>")!>In(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test6(cls: Cls) {
|
||||
id<In<Bound>>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("In<Bound>")!>In(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test7(cls: Cls) {
|
||||
id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out Cls>")!>wrapOut(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test8(cls: Cls) {
|
||||
// TODO
|
||||
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, TYPE_MISMATCH!>id<!>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<in Cls>")!>wrapIn(cls)<!>
|
||||
)
|
||||
}
|
||||
|
||||
fun test9(cls: Cls) {
|
||||
id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("InB<Bound>")!>InB(cls)<!>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ arg: K): K
|
||||
public fun </*0*/ W> makeInv(/*0*/ arg: W): Inv<W>
|
||||
public fun test1(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test2(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test3(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test4(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test5(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test6(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test7(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test8(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun test9(/*0*/ cls: Cls): kotlin.Unit
|
||||
public fun </*0*/ I> wrapIn(/*0*/ arg: I): Inv<in I>
|
||||
public fun </*0*/ O> wrapOut(/*0*/ arg: O): Inv<out O>
|
||||
|
||||
public interface Bound {
|
||||
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 final class Cls : Bound {
|
||||
public constructor Cls()
|
||||
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 final class In</*0*/ in I> {
|
||||
public constructor In</*0*/ in I>(/*0*/ param: I)
|
||||
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 final class InB</*0*/ in I : Bound> {
|
||||
public constructor InB</*0*/ in I : Bound>(/*0*/ param: I)
|
||||
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 final class Inv</*0*/ T> {
|
||||
public constructor Inv</*0*/ T>(/*0*/ prop: T)
|
||||
public final val prop: T
|
||||
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 final class Out</*0*/ out O> {
|
||||
public constructor Out</*0*/ out O>(/*0*/ prop: O)
|
||||
public final val prop: O
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// FILE: GenericRunnable.java
|
||||
|
||||
public interface GenericRunnable<T> {
|
||||
T invoke();
|
||||
}
|
||||
|
||||
// FILE: OurFuture.java
|
||||
|
||||
public class OurFuture<T> {
|
||||
static <T> OurFuture<T> createOurFuture(T result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <U> OurFuture<U> compose(GenericRunnable<OurFuture<U>> mapper) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
open class Either<out L> {
|
||||
class Left<out L>(val a: L) : Either<L>()
|
||||
}
|
||||
|
||||
fun f1(future: OurFuture<String>, e: Either.Left<String>) {
|
||||
future.compose<Either<String>> {
|
||||
val x = when {
|
||||
true -> OurFuture.createOurFuture(e)
|
||||
else -> throw Exception()
|
||||
}
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
fun f2(future: OurFuture<String>, e: Either.Left<String>) {
|
||||
future.compose<Either<String>> {
|
||||
when {
|
||||
true -> OurFuture.createOurFuture(e)
|
||||
else -> throw Exception()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// FILE: GenericRunnable.java
|
||||
|
||||
public interface GenericRunnable<T> {
|
||||
T invoke();
|
||||
}
|
||||
|
||||
// FILE: OurFuture.java
|
||||
|
||||
public class OurFuture<T> {
|
||||
static <T> OurFuture<T> createOurFuture(T result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <U> OurFuture<U> compose(GenericRunnable<OurFuture<U>> mapper) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
open class Either<out L> {
|
||||
class Left<out L>(val a: L) : Either<L>()
|
||||
}
|
||||
|
||||
fun f1(future: OurFuture<String>, e: Either.Left<String>) {
|
||||
future.compose<Either<String>> {
|
||||
val x = when {
|
||||
true -> OurFuture.createOurFuture(e)
|
||||
else -> throw Exception()
|
||||
}
|
||||
<!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>x<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun f2(future: OurFuture<String>, e: Either.Left<String>) {
|
||||
future.compose<Either<String>> {
|
||||
when {
|
||||
true -> OurFuture.createOurFuture(e)
|
||||
else -> throw Exception()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package
|
||||
|
||||
public fun f1(/*0*/ future: OurFuture<kotlin.String>, /*1*/ e: Either.Left<kotlin.String>): kotlin.Unit
|
||||
public fun f2(/*0*/ future: OurFuture<kotlin.String>, /*1*/ e: Either.Left<kotlin.String>): kotlin.Unit
|
||||
|
||||
public open class Either</*0*/ out L> {
|
||||
public constructor Either</*0*/ out L>()
|
||||
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 final class Left</*0*/ out L> : Either<L> {
|
||||
public constructor Left</*0*/ out L>(/*0*/ a: L)
|
||||
public final val a: L
|
||||
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 interface GenericRunnable</*0*/ T : kotlin.Any!> {
|
||||
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 abstract operator fun invoke(): T!
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class OurFuture</*0*/ T : kotlin.Any!> {
|
||||
public constructor OurFuture</*0*/ T : kotlin.Any!>()
|
||||
public open fun </*0*/ U : kotlin.Any!> compose(/*0*/ mapper: GenericRunnable<OurFuture<U!>!>!): OurFuture<U!>!
|
||||
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
|
||||
|
||||
// Static members
|
||||
public/*package*/ open fun </*0*/ T : kotlin.Any!> createOurFuture(/*0*/ result: T!): OurFuture<T!>!
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun takeByte(ilt: Byte) {}
|
||||
fun takeShort(ilt: Short) {}
|
||||
fun takeInt(ilt: Int) {}
|
||||
fun takeLong(ilt: Long) {}
|
||||
|
||||
fun <T> id(arg: T): T = arg
|
||||
|
||||
fun test() {
|
||||
takeByte(id(42))
|
||||
takeShort(id(42))
|
||||
takeInt(id(42))
|
||||
takeLong(id(42))
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun takeByte(ilt: Byte) {}
|
||||
fun takeShort(ilt: Short) {}
|
||||
fun takeInt(ilt: Int) {}
|
||||
fun takeLong(ilt: Long) {}
|
||||
|
||||
fun <T> id(arg: T): T = arg
|
||||
|
||||
fun test() {
|
||||
takeByte(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Byte")!>id(42)<!>)
|
||||
takeShort(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Short")!>id(42)<!>)
|
||||
takeInt(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>id(42)<!>)
|
||||
takeLong(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Long")!>id(42)<!>)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> id(/*0*/ arg: T): T
|
||||
public fun takeByte(/*0*/ ilt: kotlin.Byte): kotlin.Unit
|
||||
public fun takeInt(/*0*/ ilt: kotlin.Int): kotlin.Unit
|
||||
public fun takeLong(/*0*/ ilt: kotlin.Long): kotlin.Unit
|
||||
public fun takeShort(/*0*/ ilt: kotlin.Short): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
@@ -0,0 +1,26 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
import kotlin.internal.Exact
|
||||
|
||||
class Inv<I>(val arg: I)
|
||||
class InvExact<E>(val arg: @kotlin.internal.Exact E)
|
||||
|
||||
interface Base
|
||||
class Derived : Base
|
||||
class Other : Base
|
||||
|
||||
fun <K> id(arg: K): K = arg
|
||||
|
||||
fun test1(arg: Derived) {
|
||||
id<Inv<Base>>(Inv(arg))
|
||||
<!INAPPLICABLE_CANDIDATE!>id<!><Inv<Base>>(InvExact(arg))
|
||||
}
|
||||
|
||||
fun <R> Inv<@Exact R>.select(first: R, second: R): R = TODO()
|
||||
|
||||
fun test2(derived: Derived, other: Other) {
|
||||
Inv(derived).<!INAPPLICABLE_CANDIDATE!>select<!>(derived, other)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
import kotlin.internal.Exact
|
||||
|
||||
class Inv<I>(val arg: I)
|
||||
class InvExact<E>(val arg: @kotlin.internal.Exact E)
|
||||
|
||||
interface Base
|
||||
class Derived : Base
|
||||
class Other : Base
|
||||
|
||||
fun <K> id(arg: K): K = arg
|
||||
|
||||
fun test1(arg: Derived) {
|
||||
id<Inv<Base>>(Inv(arg))
|
||||
id<Inv<Base>>(<!TYPE_MISMATCH!>InvExact(arg)<!>)
|
||||
}
|
||||
|
||||
fun <R> Inv<@Exact R>.select(first: R, second: R): R = TODO()
|
||||
|
||||
fun test2(derived: Derived, other: Other) {
|
||||
Inv(derived).select(derived, <!TYPE_MISMATCH!>other<!>)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ arg: K): K
|
||||
public fun test1(/*0*/ arg: Derived): kotlin.Unit
|
||||
public fun test2(/*0*/ derived: Derived, /*1*/ other: Other): kotlin.Unit
|
||||
public fun </*0*/ R> Inv<R>.select(/*0*/ first: R, /*1*/ second: R): R
|
||||
|
||||
public interface Base {
|
||||
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 final class Derived : Base {
|
||||
public constructor Derived()
|
||||
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 final class Inv</*0*/ I> {
|
||||
public constructor Inv</*0*/ I>(/*0*/ arg: I)
|
||||
public final val arg: I
|
||||
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 final class InvExact</*0*/ E> {
|
||||
public constructor InvExact</*0*/ E>(/*0*/ arg: E)
|
||||
public final val arg: E
|
||||
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 final class Other : Base {
|
||||
public constructor Other()
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user