FIR: Fix callable references resolution when they're being returned from lambdas

This commit is contained in:
Denis.Zharkov
2021-01-13 21:28:23 +03:00
parent 0e368cc237
commit ad30c6c380
7 changed files with 19 additions and 56 deletions
@@ -263,13 +263,15 @@ class FirCallResolver(
conflictResolver.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
}
resolvedCallableReferenceAtom.hasBeenResolvedOnce = true
when {
noSuccessfulCandidates -> {
return false
}
reducedCandidates.size > 1 -> {
if (resolvedCallableReferenceAtom.postponed) return false
resolvedCallableReferenceAtom.postponed = true
if (resolvedCallableReferenceAtom.hasBeenPostponed) return false
resolvedCallableReferenceAtom.hasBeenPostponed = true
return true
}
}
@@ -291,8 +291,9 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
postponedAtom.collectNotFixedVariables()
}
postponedAtom is ResolvedCallableReferenceAtom -> {
if (postponedAtom.postponed)
if (postponedAtom.mightNeedAdditionalResolution) {
postponedAtom.collectNotFixedVariables()
}
}
}
}
@@ -68,7 +68,7 @@ class PostponedArgumentsAnalyzer(
}
private fun processCallableReference(atom: ResolvedCallableReferenceAtom, candidate: Candidate) {
if (atom.postponed) {
if (atom.mightNeedAdditionalResolution) {
callResolver.resolveCallableReference(candidate.csBuilder, atom)
}
@@ -116,35 +116,38 @@ class ResolvedCallableReferenceAtom(
val lhs: DoubleColonLHS?,
private val session: FirSession
) : PostponedResolvedAtom(), PostponedCallableReferenceMarker {
// TODO: in several places atoms are filtered by the marker interface - potential overhead/errors
var postponed: Boolean = false
var hasBeenResolvedOnce: Boolean = false
var hasBeenPostponed: Boolean = false
val mightNeedAdditionalResolution get() = !hasBeenResolvedOnce || hasBeenPostponed
var resultingCandidate: Pair<Candidate, CandidateApplicability>? = null
override val inputTypes: Collection<ConeKotlinType>
get() {
if (!postponed) return emptyList()
if (!hasBeenPostponed) return emptyList()
return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session)?.inputTypes
?: listOfNotNull(expectedType)
}
override val outputType: ConeKotlinType?
get() {
if (!postponed) return null
if (!hasBeenPostponed) return null
return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session)?.outputType
}
override val expectedType: ConeKotlinType?
get() = if (!postponed)
get() = if (!hasBeenPostponed)
initialExpectedType
else
revisedExpectedType ?: initialExpectedType
override var revisedExpectedType: ConeKotlinType? = null
get() = if (postponed) field else expectedType
get() = if (hasBeenPostponed) field else expectedType
private set
override fun reviseExpectedType(expectedType: KotlinTypeMarker) {
if (!postponed) return
if (!mightNeedAdditionalResolution) return
require(expectedType is ConeKotlinType)
revisedExpectedType = expectedType
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: 1.kt
package test
@@ -38,4 +37,4 @@ class A {
fun box(): String {
A().test()
return result
}
}
@@ -1,43 +0,0 @@
// SKIP_TXT
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +NewInference
interface Inv<T>
fun <E> Inv<E>.foo(
handler: () -> ((command: E) -> Unit)
) {}
fun bar(x: Int) {}
fun bar(x: String) {}
fun bar1(arg: Int) {}
fun foo1(f: () -> (Int) -> Unit) = ""
fun main(x: Inv<Int>) {
x.foo<Int> {
if (x.hashCode() == 0) return@foo <!UNRESOLVED_REFERENCE!>::bar<!>
::bar
}
x.foo {
if (x.hashCode() == 0) return@foo <!UNRESOLVED_REFERENCE!>::bar<!>
::bar
}
foo1 {
::bar1
}
foo1 {
return@foo1 ::bar1
}
foo1 {
if (x.hashCode() == 0) return@foo1 ::bar
::bar
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +NewInference