[FIR] Replace type variable types with error types in lambda completion
#KT-54568 Fixed #KT-59882
This commit is contained in:
committed by
Space Team
parent
48433bf9fd
commit
80200fc3c5
+1
@@ -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
|
||||
|
||||
+16
-5
@@ -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<!> ->
|
||||
|
||||
+3
-4
@@ -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
@@ -1,4 +1,3 @@
|
||||
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
|
||||
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
fun <T> select(vararg x: T) = x[0]
|
||||
|
||||
Vendored
+3
-4
@@ -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<!>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun callAny(arg: Any?) {}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
|
||||
// !LANGUAGE: +PartiallySpecifiedTypeArguments
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
// WITH_STDLIB
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_LEAKED_INTERNAL_TYPES: KT-54568
|
||||
// !LANGUAGE: +PartiallySpecifiedTypeArguments
|
||||
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||
// WITH_STDLIB
|
||||
|
||||
+6
-2
@@ -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
@@ -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
@@ -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<!> {
|
||||
|
||||
Reference in New Issue
Block a user