[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:
Pavel Kirpichenkov
2019-12-16 19:02:03 +03:00
parent a9391c8dfb
commit e9941f8c12
17 changed files with 735 additions and 64 deletions
@@ -10362,6 +10362,39 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractFirOldFrontendDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt");
}
@TestMetadata("kt33166.kt")
public void testKt33166() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt");
}
@TestMetadata("partialForIlt.kt")
public void testPartialForIlt() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt");
}
@TestMetadata("withExact.kt")
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,176 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.*
import java.util.*
typealias CsCompleterContext = KotlinConstraintSystemCompleter.Context
class CompletionModeCalculator {
companion object {
fun computeCompletionMode(
candidate: KotlinResolutionCandidate,
expectedType: UnwrappedType?,
returnType: UnwrappedType?
): ConstraintSystemCompletionMode = with(candidate) {
val csCompleterContext = getSystem().asConstraintSystemCompleterContext()
// Presence of expected type means that we are trying to complete outermost call => completion mode should be full
if (expectedType != null) return ConstraintSystemCompletionMode.FULL
// This is questionable as null return type can be only for error call
if (returnType == null) return ConstraintSystemCompletionMode.PARTIAL
// Full if return type for call has no type variables
if (csBuilder.isProperType(returnType)) return ConstraintSystemCompletionMode.FULL
// For nested call with variables in return type check possibility of full completion
return CalculatorForNestedCall(returnType, csCompleterContext).computeCompletionMode()
}
}
private class CalculatorForNestedCall(
private val returnType: UnwrappedType?,
private val csCompleterContext: CsCompleterContext
) {
private enum class FixationDirection {
TO_SUBTYPE, TO_SUPERTYPE, EQUALITY
}
private val fixationDirectionsForVariables = mutableMapOf<VariableWithConstraints, FixationDirection>()
private val variablesWithQueuedConstraints = mutableSetOf<TypeVariableMarker>()
private val typesToProcess: Queue<KotlinTypeMarker> = ArrayDeque()
fun computeCompletionMode(): ConstraintSystemCompletionMode = with(csCompleterContext) {
// Add fixation directions for variables based on effective variance in type
typesToProcess.add(returnType)
computeDirections()
// If all variables have required proper constraint, run full completion
if (directionRequirementsForVariablesHold())
return ConstraintSystemCompletionMode.FULL
return ConstraintSystemCompletionMode.PARTIAL
}
private fun CsCompleterContext.computeDirections() {
while (typesToProcess.isNotEmpty()) {
val type = typesToProcess.poll() ?: break
fixationRequirementForTopLevel(type)?.let { directionForVariable ->
updateDirection(directionForVariable)
enqueueTypesFromConstraints(directionForVariable.variable)
}
// find all variables in type and make requirements for them
type.contains { fromReturnType ->
for (directionForVariable in directionsForVariablesInTypeArguments(fromReturnType)) {
updateDirection(directionForVariable)
enqueueTypesFromConstraints(directionForVariable.variable)
}
false
}
}
}
private fun enqueueTypesFromConstraints(variableWithConstraints: VariableWithConstraints) {
val variable = variableWithConstraints.typeVariable
if (variable !in variablesWithQueuedConstraints) {
for (constraint in variableWithConstraints.constraints) {
typesToProcess.add(constraint.type)
}
variablesWithQueuedConstraints.add(variable)
}
}
private fun CsCompleterContext.directionRequirementsForVariablesHold(): Boolean {
for ((variable, fixationDirection) in fixationDirectionsForVariables) {
if (!hasProperConstraint(variable, fixationDirection))
return false
}
return true
}
private fun updateDirection(directionForVariable: FixationDirectionForVariable) {
val (variable, newDirection) = directionForVariable
fixationDirectionsForVariables[variable]?.let { oldDirection ->
// To sub and to super are merged into equality, old equality stays
if (oldDirection != FixationDirection.EQUALITY && oldDirection != newDirection)
fixationDirectionsForVariables[variable] = FixationDirection.EQUALITY
}
fixationDirectionsForVariables[variable] = newDirection
}
private data class FixationDirectionForVariable(val variable: VariableWithConstraints, val direction: FixationDirection)
private fun CsCompleterContext.fixationRequirementForTopLevel(type: KotlinTypeMarker): FixationDirectionForVariable? {
return notFixedTypeVariables[type.typeConstructor()]?.let {
FixationDirectionForVariable(it, FixationDirection.TO_SUBTYPE)
}
}
private fun CsCompleterContext.directionsForVariablesInTypeArguments(type: KotlinTypeMarker): List<FixationDirectionForVariable> {
assert(type.argumentsCount() == type.typeConstructor().parametersCount()) {
"Arguments and parameters count don't match for type $type. " +
"Arguments: ${type.argumentsCount()}, parameters: ${type.typeConstructor().parametersCount()}"
}
val directionsForVariables = mutableListOf<FixationDirectionForVariable>()
for (position in 0 until type.argumentsCount()) {
val argument = type.getArgument(position)
if (!argument.getType().mayBeTypeVariable())
continue
val variableWithConstraints = notFixedTypeVariables[argument.getType().typeConstructor()] ?: continue
val parameter = type.typeConstructor().getParameter(position)
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
?: TypeVariance.OUT // Discuss
val direction = when (effectiveVariance) {
TypeVariance.IN -> FixationDirection.TO_SUPERTYPE
TypeVariance.OUT -> FixationDirection.TO_SUBTYPE
TypeVariance.INV -> FixationDirection.EQUALITY
}
val requirement = FixationDirectionForVariable(variableWithConstraints, direction)
directionsForVariables.add(requirement)
}
return directionsForVariables
}
private fun CsCompleterContext.hasProperConstraint(
variableWithConstraints: VariableWithConstraints,
direction: FixationDirection
): Boolean {
val constraints = variableWithConstraints.constraints
// todo check correctness for @Exact
return constraints.isNotEmpty() && constraints.any { constraint ->
constraint.hasRequiredKind(direction)
&& !constraint.type.typeConstructor().isIntegerLiteralTypeConstructor()
&& isProperType(constraint.type)
}
}
private fun Constraint.hasRequiredKind(direction: FixationDirection) = when (direction) {
FixationDirection.TO_SUBTYPE -> kind.isLower() || kind.isEqual()
FixationDirection.TO_SUPERTYPE -> kind.isUpper() || kind.isEqual()
FixationDirection.EQUALITY -> kind.isEqual()
}
}
}
@@ -53,7 +53,7 @@ class KotlinCallCompleter(
return if (resolutionCallbacks.inferenceSession.shouldRunCompletion(candidate))
candidate.runCompletion(
candidate.computeCompletionMode(expectedType, returnType),
CompletionModeCalculator.computeCompletionMode(candidate, expectedType, returnType),
diagnosticHolder,
resolutionCallbacks
)
@@ -208,69 +208,6 @@ class KotlinCallCompleter(
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPosition(resolvedCall.atom))
}
private fun KotlinResolutionCandidate.computeCompletionMode(
expectedType: UnwrappedType?,
currentReturnType: UnwrappedType?
): ConstraintSystemCompletionMode {
// Presence of expected type means that we trying to complete outermost call => completion mode should be full
if (expectedType != null) return ConstraintSystemCompletionMode.FULL
// This is questionable as null return type can be only for error call
if (currentReturnType == null) return ConstraintSystemCompletionMode.PARTIAL
return when {
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
// Otherwise, we shouldn't complete bar until we process call foo
csBuilder.isProperType(currentReturnType) -> ConstraintSystemCompletionMode.FULL
// Nested call is connected with the outer one through the UPPER constraint (returnType <: expectedOuterType)
// This means that there will be no new LOWER constraints =>
// it's possible to complete call now if there are proper LOWER constraints
csBuilder.isTypeVariable(currentReturnType) ->
if (hasProperNonTrivialLowerConstraints(currentReturnType))
ConstraintSystemCompletionMode.FULL
else
ConstraintSystemCompletionMode.PARTIAL
// Return type has proper equal constraints => there is no need in the outer call
containsTypeVariablesWithProperEqualConstraints(currentReturnType) -> ConstraintSystemCompletionMode.FULL
else -> ConstraintSystemCompletionMode.PARTIAL
}
}
private fun KotlinResolutionCandidate.containsTypeVariablesWithProperEqualConstraints(type: UnwrappedType): Boolean {
for ((variableConstructor, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
if (!type.contains { it.constructor == variableConstructor }) continue
val constraints = variableWithConstraints.constraints
val onlyProperEqualConstraints =
constraints.isNotEmpty() && constraints.any { it.kind.isEqual() && csBuilder.isProperType(it.type) }
if (!onlyProperEqualConstraints) return false
}
return true
}
private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean {
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
val context = getSystem() as TypeSystemInferenceExtensionContext
val constructor = typeVariable.constructor
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
val constraints = variableWithConstraints.constraints
return constraints.isNotEmpty() && constraints.anyOrAll(requireAll = typeVariable.hasExactAnnotation()) {
!it.type.typeConstructor(context).isIntegerLiteralTypeConstructor(context) &&
(it.kind.isLower() || it.kind.isEqual()) &&
csBuilder.isProperType(it.type) &&
!trivialConstraintTypeInferenceOracle.isNotInterestingConstraint(it)
}
}
private inline fun <T> Iterable<T>.anyOrAll(requireAll: Boolean, p: (T) -> Boolean): Boolean =
if (requireAll) all(p) else any(p)
fun KotlinResolutionCandidate.asCallResolutionResult(
type: ConstraintSystemCompletionMode,
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder
@@ -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!>!
}
@@ -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
}
@@ -10369,6 +10369,39 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt");
}
@TestMetadata("kt33166.kt")
public void testKt33166() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt");
}
@TestMetadata("partialForIlt.kt")
public void testPartialForIlt() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt");
}
@TestMetadata("withExact.kt")
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10364,6 +10364,39 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractDiagnosticsUsingJavacTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt");
}
@TestMetadata("kt33166.kt")
public void testKt33166() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt");
}
@TestMetadata("partialForIlt.kt")
public void testPartialForIlt() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt");
}
@TestMetadata("withExact.kt")
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)