[NI] Skip fake call for descriptor from object in builder-inference

This call have interesting rules for resolution, see
 `KtQualifiedExpression.elementChain` function and it's usages:
 resolution results for such call can be omitted and be replaced with
 some other information, while diagnostics will be reported from
 builder-inference.

 To mitigate this problem, we'll just skip this call from builder-inference
 as such calls can't have type parameters anyway

 #KT-32094 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-06-20 16:27:13 +03:00
parent bebdf6fcef
commit fe0282809e
5 changed files with 18 additions and 9 deletions
@@ -84,7 +84,7 @@ class DelegatedPropertyInferenceSession(
initialStorage: ConstraintStorage initialStorage: ConstraintStorage
): Map<TypeConstructor, UnwrappedType> = emptyMap() ): Map<TypeConstructor, UnwrappedType> = emptyMap()
override fun writeOnlyStubs(): Boolean = false override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
} }
object InferenceSessionForExistingCandidates : InferenceSession { object InferenceSessionForExistingCandidates : InferenceSession {
@@ -102,6 +102,6 @@ object InferenceSessionForExistingCandidates : InferenceSession {
initialStorage: ConstraintStorage initialStorage: ConstraintStorage
): Map<TypeConstructor, UnwrappedType> = emptyMap() ): Map<TypeConstructor, UnwrappedType> = emptyMap()
override fun writeOnlyStubs(): Boolean = false override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImp
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
@@ -58,6 +59,8 @@ class CoroutineInferenceSession(
override fun addCompletedCallInfo(callInfo: CompletedCallInfo) { override fun addCompletedCallInfo(callInfo: CompletedCallInfo) {
require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" } require(callInfo is PSICompletedCallInfo) { "Wrong instance of callInfo: $callInfo" }
if (skipCall(callInfo.callResolutionResult)) return
commonCalls.add(callInfo) commonCalls.add(callInfo)
val isApplicableCall = val isApplicableCall =
@@ -71,8 +74,15 @@ class CoroutineInferenceSession(
} }
} }
override fun writeOnlyStubs(): Boolean { override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean {
return true return !skipCall(callInfo)
}
private fun skipCall(callInfo: SingleCallResolutionResult): Boolean {
// FakeCallableDescriptorForObject can't introduce new information for inference, so it's safe to complete it fully
if (callInfo.resultCallAtom.candidateDescriptor is FakeCallableDescriptorForObject) return true
return false
} }
override fun currentConstraintSystem(): ConstraintStorage { override fun currentConstraintSystem(): ConstraintStorage {
@@ -110,7 +110,7 @@ class KotlinToResolvedCallTransformer(
val candidate = (baseResolvedCall as SingleCallResolutionResult).resultCallAtom val candidate = (baseResolvedCall as SingleCallResolutionResult).resultCallAtom
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor(typeSystemContext) val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor(typeSystemContext)
if (context.inferenceSession.writeOnlyStubs()) { if (context.inferenceSession.writeOnlyStubs(baseResolvedCall)) {
val stub = createStubResolvedCallAndWriteItToTrace<CallableDescriptor>( val stub = createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(
candidate, candidate,
context.trace, context.trace,
@@ -24,7 +24,7 @@ interface InferenceSession {
initialStorage: ConstraintStorage initialStorage: ConstraintStorage
): Map<TypeConstructor, UnwrappedType> = emptyMap() ): Map<TypeConstructor, UnwrappedType> = emptyMap()
override fun writeOnlyStubs(): Boolean = false override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false override fun callCompleted(resolvedAtom: ResolvedAtom): Boolean = false
} }
} }
@@ -35,7 +35,7 @@ interface InferenceSession {
fun addErrorCallInfo(callInfo: ErrorCallInfo) fun addErrorCallInfo(callInfo: ErrorCallInfo)
fun currentConstraintSystem(): ConstraintStorage fun currentConstraintSystem(): ConstraintStorage
fun inferPostponedVariables(lambda: ResolvedLambdaAtom, initialStorage: ConstraintStorage): Map<TypeConstructor, UnwrappedType> fun inferPostponedVariables(lambda: ResolvedLambdaAtom, initialStorage: ConstraintStorage): Map<TypeConstructor, UnwrappedType>
fun writeOnlyStubs(): Boolean fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean
fun callCompleted(resolvedAtom: ResolvedAtom): Boolean fun callCompleted(resolvedAtom: ResolvedAtom): Boolean
} }
@@ -1,6 +1,5 @@
// !USE_EXPERIMENTAL: kotlin.Experimental // !USE_EXPERIMENTAL: kotlin.Experimental
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
// !WITH_NEW_INFERENCE
// FILE: a.kt // FILE: a.kt
@@ -36,7 +35,7 @@ fun <T> invBuilder(@BuilderInference block: Inv<T>.() -> Unit) {}
fun test() { fun test() {
invBuilder { invBuilder {
val q = <!NI;INVISIBLE_MEMBER!>Queue<!>.empty() val q = Queue.empty()
emit(42) emit(42)
} }
} }