[FIR] Fix inference of postponed lambdas if containg call has explicit type arguments

This commit is contained in:
Dmitriy Novozhilov
2022-01-19 16:50:37 +03:00
committed by TeamCityServer
parent fbab32c4dd
commit def799cc4e
7 changed files with 131 additions and 1 deletions
@@ -2859,6 +2859,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt");
}
@Test
@TestMetadata("lambdaWithoutExpectedType.kt")
public void testLambdaWithoutExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaWithoutExpectedType.kt");
}
@Test
@TestMetadata("lambdasReturns.kt")
public void testLambdasReturns() throws Exception {
@@ -2511,6 +2511,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt");
}
@TestMetadata("lambdaWithoutExpectedType.kt")
public void testLambdaWithoutExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaWithoutExpectedType.kt");
}
@TestMetadata("lambdasReturns.kt")
public void testLambdasReturns() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdasReturns.kt");
@@ -0,0 +1,60 @@
FILE: lambdaWithoutExpectedType.kt
public abstract interface XdEntity : R|kotlin/Any| {
}
public abstract interface XdEntityType<out T : R|XdEntity|> : R|kotlin/Any| {
}
public abstract interface XdNaturalEntityType<T : R|XdEntity|> : R|XdEntityType<T>| {
}
public final class XdProject : R|XdEntity| {
public constructor(name: R|kotlin/String|): R|XdProject| {
super<R|kotlin/Any|>()
}
public final var name: R|kotlin/String| = R|<local>/name|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
public final companion object Companion : R|XdNaturalEntityType<XdProject>| {
private constructor(): R|XdProject.Companion| {
super<R|kotlin/Any|>()
}
}
}
public abstract interface XdSearchingNode : R|kotlin/Any| {
}
public abstract interface XdQuery<out T : R|XdEntity|> : R|kotlin/Any| {
}
public final fun <T : R|XdEntity|> R|XdQuery<T>|.firstOrNull(): R|T?| {
^firstOrNull Null(null)
}
public final object FilteringContext : R|kotlin/Any| {
private constructor(): R|FilteringContext| {
super<R|kotlin/Any|>()
}
public final infix fun <T : R|kotlin/Comparable<T>|> R|T?|.eq(value: R|T?|): R|XdSearchingNode| {
^eq Null(null)!!
}
}
public final fun <T : R|XdEntity|> R|XdEntityType<T>|.filter(clause: R|FilteringContext.(T) -> XdSearchingNode|): R|XdQuery<T>| {
^filter Null(null)!!
}
public abstract interface XdIssue : R|kotlin/Any| {
}
public abstract interface XdIssueFolder : R|kotlin/Any| {
}
public final fun test(): R|kotlin/Unit| {
lval array: R|kotlin/Array<kotlin/Any>| = R|kotlin/arrayOf|<R|kotlin/Any|>(vararg(String(Project), arrayOf@fun <anonymous>(): R|XdProject?| <inline=Unknown, kind=UNKNOWN> {
^ Q|XdProject|.R|/filter|<R|XdProject|>(<L> = filter@fun R|FilteringContext|.<anonymous>(it: R|XdProject|): R|XdSearchingNode| <inline=NoInline> {
^ (this@R|special/anonymous|, R|<local>/it|.R|/XdProject.name|).R|/FilteringContext.eq|<R|kotlin/String|>(String(foo))
}
).R|/firstOrNull|<R|XdProject|>()
}
, arrayOf@fun <anonymous>(<unused var>: R|XdIssue|, <unused var>: R|XdIssueFolder|): R|kotlin/Unit| <inline=Unknown, kind=UNKNOWN> {
^@arrayOf Unit
}
))
}
@@ -0,0 +1,34 @@
// WITH_STDLIB
interface XdEntity
interface XdEntityType<out T : XdEntity>
interface XdNaturalEntityType<T : XdEntity> : XdEntityType<T>
class XdProject(var name: String) : XdEntity {
companion object : XdNaturalEntityType<XdProject> {}
}
interface XdSearchingNode
interface XdQuery<out T : XdEntity>
fun <T : XdEntity> XdQuery<T>.firstOrNull(): T? = null
object FilteringContext {
infix fun <T : Comparable<T>> T?.eq(value: T?): XdSearchingNode = null!!
}
fun <T : XdEntity> XdEntityType<T>.filter(clause: FilteringContext.(T) -> XdSearchingNode): XdQuery<T> {
return null!!
}
interface XdIssue
interface XdIssueFolder
fun test() {
val array = arrayOf<Any>(
"Project",
{ XdProject.filter { it.name eq "foo" }.firstOrNull() },
{ _: XdIssue, _: XdIssueFolder -> }
)
}
@@ -2859,6 +2859,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt");
}
@Test
@TestMetadata("lambdaWithoutExpectedType.kt")
public void testLambdaWithoutExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaWithoutExpectedType.kt");
}
@Test
@TestMetadata("lambdasReturns.kt")
public void testLambdasReturns() throws Exception {
@@ -2859,6 +2859,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaInElvis.kt");
}
@Test
@TestMetadata("lambdaWithoutExpectedType.kt")
public void testLambdaWithoutExpectedType() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaWithoutExpectedType.kt");
}
@Test
@TestMetadata("lambdasReturns.kt")
public void testLambdasReturns() throws Exception {
@@ -15,9 +15,12 @@ import org.jetbrains.kotlin.fir.resolve.calls.CheckerSink
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExplicitTypeParameterConstraintPosition
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.types.model.typeConstructor
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun Candidate.preprocessLambdaArgument(
@@ -31,7 +34,17 @@ fun Candidate.preprocessLambdaArgument(
returnTypeVariable: ConeTypeVariableForLambdaReturnType? = null
): PostponedResolvedAtom {
if (expectedType != null && expectedTypeRef != null && !duringCompletion && csBuilder.isTypeVariable(expectedType)) {
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType, expectedTypeRef, this)
val expectedTypeVariableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[expectedType.typeConstructor(context.typeContext)]
if (expectedTypeVariableWithConstraints != null) {
val explicitTypeArgument = expectedTypeVariableWithConstraints.constraints.find {
it.kind == ConstraintKind.EQUALITY && it.position.from is ConeExplicitTypeParameterConstraintPosition
}?.type as ConeKotlinType?
if (explicitTypeArgument == null || explicitTypeArgument.typeArguments.isNotEmpty()) {
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType, expectedTypeRef, this)
}
}
}
val anonymousFunction = argument.anonymousFunction