[FIR] Replace type variable types with error types in lambda completion

#KT-54568 Fixed
#KT-59882
This commit is contained in:
Kirill Rakhman
2023-08-07 16:30:01 +02:00
committed by Space Team
parent 48433bf9fd
commit 80200fc3c5
16 changed files with 46 additions and 50 deletions
@@ -125,6 +125,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeDestructuringDeclarationsOnTopLevel -> null // TODO Currently a parsing error. Would be better to report here instead KT-58563
is ConeCannotInferTypeParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeCannotInferValueParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeCannotInferReceiverParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeTypeVariableTypeIsNotInferred -> FirErrors.INFERENCE_ERROR.createOn(callOrAssignmentSource ?: source)
is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.createOn(source, this.target)
is ConeStubDiagnostic -> null
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildContextReceiver
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferReceiverParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferValueParameterType
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.*
@@ -263,9 +265,9 @@ class FirCallCompleter(
containingFunctionSymbol = lambdaArgument.symbol
moduleData = session.moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = itType.approximateLambdaInputType().toFirResolvedTypeRef()
this.name = name
symbol = FirValueParameterSymbol(name)
returnTypeRef = itType.approximateLambdaInputType(symbol).toFirResolvedTypeRef()
defaultValue = null
isCrossinline = false
isNoinline = false
@@ -281,7 +283,7 @@ class FirCallCompleter(
receiverType == null -> lambdaArgument.replaceReceiverParameter(null)
!lambdaAtom.coerceFirstParameterToExtensionReceiver -> {
lambdaArgument.receiverParameter?.apply {
val type = receiverType.approximateLambdaInputType()
val type = receiverType.approximateLambdaInputType(valueParameter = null)
val source = source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
replaceTypeRef(typeRef.resolvedTypeFromPrototype(type, source))
}
@@ -311,7 +313,7 @@ class FirCallCompleter(
else -> parameters
}
lambdaArgument.valueParameters.forEachIndexed { index, parameter ->
val newReturnType = theParameters[index].approximateLambdaInputType()
val newReturnType = theParameters[index].approximateLambdaInputType(parameter.symbol)
val newReturnTypeRef = if (parameter.returnTypeRef is FirImplicitTypeRef) {
newReturnType.toFirResolvedTypeRef(parameter.source?.fakeElement(KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter))
} else parameter.returnTypeRef.resolvedTypeFromPrototype(newReturnType)
@@ -352,10 +354,19 @@ class FirCallCompleter(
}
}
private fun ConeKotlinType.approximateLambdaInputType(): ConeKotlinType =
session.typeApproximator.approximateToSuperType(
private fun ConeKotlinType.approximateLambdaInputType(valueParameter: FirValueParameterSymbol?): ConeKotlinType {
// We only run lambda completion from ConstraintSystemCompletionContext.analyzeRemainingNotAnalyzedPostponedArgument when they are
// left uninferred.
// Currently, we use stub types for builder inference, so CANNOT_INFER_PARAMETER_TYPE is the only possible result here.
if (this is ConeTypeVariableType) {
val diagnostic = valueParameter?.let(::ConeCannotInferValueParameterType) ?: ConeCannotInferReceiverParameterType()
return ConeErrorType(diagnostic)
}
return session.typeApproximator.approximateToSuperType(
this, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: this
}
}
private fun Candidate.isFunctionForExpectTypeFromCastFeature(): Boolean {
@@ -37,6 +37,10 @@ class ConeCannotInferValueParameterType(
override val reason: String = "Cannot infer type for parameter ${valueParameter.name}"
) : ConeDiagnostic
class ConeCannotInferReceiverParameterType(
override val reason: String = "Cannot infer type for receiver parameter"
) : ConeDiagnostic
class ConeTypeVariableTypeIsNotInferred(
val typeVariableType: ConeTypeVariableType,
override val reason: String = "Type for ${typeVariableType.lookupTag.debugName} is not inferred"
@@ -1,24 +0,0 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
fun test1() {
try {
{ toDouble ->
}
} catch (e: Exception) {
}
}
fun test2() {
try {
} catch (e: Exception) {
{ toDouble ->
}
}
}
fun box(): String {
test1()
test2()
return "OK"
}
@@ -1,4 +1,4 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// FIR_IDENTICAL
fun test1() {
try {
{ <!CANNOT_INFER_PARAMETER_TYPE!>toDouble<!> ->
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE
fun <T> select(vararg x: <!CANNOT_INFER_PARAMETER_TYPE, CANNOT_INFER_PARAMETER_TYPE!>T<!>) = x[0]
@@ -6,12 +5,12 @@ fun <K> id(x: K) = x
fun main() {
val x1 = select<Any?>(id { x, y -> }, { x: Int, y -> })
val x2 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>select<!>(id { x, y -> }, { x: Int, y -> })
val x2 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>select<!>(id { x, <!CANNOT_INFER_PARAMETER_TYPE!>y<!> -> }, { x: Int, <!CANNOT_INFER_PARAMETER_TYPE!>y<!> -> })
val x3 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>select<!>(id(fun (x, y) {}), fun (x: Int, y) {})
val x3 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>select<!>(id(fun (x, <!CANNOT_INFER_PARAMETER_TYPE!>y<!>) {}), fun (x: Int, <!CANNOT_INFER_PARAMETER_TYPE!>y<!>) {})
val x4 = select<Any?>((fun (x, y) {}), fun (x: Int, y) {})
val x5 = select<Any?>(id(fun (x, y) {}), fun (x: Int, y) {})
val x5 = select<Any?>(id(fun (<!CANNOT_INFER_PARAMETER_TYPE!>x<!>, <!CANNOT_INFER_PARAMETER_TYPE!>y<!>) {}), fun (x: Int, y) {})
val x6 = id<Any?>(fun (x) {})
select<Any?>(fun (x) {}, fun (x) {})
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE
fun <T> select(vararg x: T) = x[0]
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun callAny(arg: Any?) {}
@@ -20,14 +19,14 @@ fun testAnyCall() {
}
fun testParam() {
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>callParam<!> {
param -> param
callParam {
<!CANNOT_INFER_PARAMETER_TYPE!>param<!> -> param
}
}
fun testParamCall() {
callParam {
param -> <!UNRESOLVED_REFERENCE!>param<!>()
<!CANNOT_INFER_PARAMETER_TYPE!>param<!> -> <!UNRESOLVED_REFERENCE!>param<!>()
}
}
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun callAny(arg: Any?) {}
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !LANGUAGE: +PartiallySpecifiedTypeArguments
// !DIAGNOSTICS: -UNCHECKED_CAST
// WITH_STDLIB
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// !LANGUAGE: +PartiallySpecifiedTypeArguments
// !DIAGNOSTICS: -UNCHECKED_CAST
// WITH_STDLIB
+6 -2
View File
@@ -1,3 +1,7 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
fun <K> foo(x: K) {}
val x = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { it.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x1 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { it.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x2 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> it.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x3 = foo<<!UNRESOLVED_REFERENCE!>unresolved<!>.() -> Float> { this.<!UNRESOLVED_REFERENCE!>toFloat<!>() }
val x4 = foo<(Array<<!UNRESOLVED_REFERENCE!>unresolved<!>>) -> Int> { it.size }
fun <T> bar() = foo<(T) -> String> { it.toString() }
+6 -2
View File
@@ -1,3 +1,7 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
fun <K> foo(x: K) {}
val x = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toFloat<!>() }
val x1 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toFloat<!>() }
val x2 = foo<(<!UNRESOLVED_REFERENCE!>unresolved<!>) -> Float> { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toFloat<!>() }
val x3 = foo<<!UNRESOLVED_REFERENCE!>unresolved<!>.() -> Float> { this.<!DEBUG_INFO_MISSING_UNRESOLVED!>toFloat<!>() }
val x4 = foo<(Array<<!UNRESOLVED_REFERENCE!>unresolved<!>>) -> Int> { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!>.size }
fun <T> bar() = foo<(T) -> String> { it.toString() }
+5 -1
View File
@@ -1,4 +1,8 @@
package
public val x: kotlin.Unit
public val x1: kotlin.Unit
public val x2: kotlin.Unit
public val x3: kotlin.Unit
public val x4: kotlin.Unit
public fun </*0*/ T> bar(): kotlin.Unit
public fun </*0*/ K> foo(/*0*/ x: K): kotlin.Unit
@@ -1,8 +1,7 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// NI_EXPECTED_FILE
// See EA-76890 / KT-10843: NPE during analysis
fun lambda(x : Int?) = x?.<!FUNCTION_CALL_EXPECTED!>let<!> <!UNRESOLVED_REFERENCE!>l<!> {
y ->
<!CANNOT_INFER_PARAMETER_TYPE!>y<!> ->
if (y <!UNRESOLVED_REFERENCE!>><!> 0) return@l x
y
}<!NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION!>!!<!>
@@ -1,4 +1,3 @@
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
// NI_EXPECTED_FILE
// See EA-76890 / KT-10843: NPE during analysis
fun lambda(x : Int?) = x?.<!FUNCTION_CALL_EXPECTED, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>let<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>l<!> {