[FIR] Fix reporting of CANNOT_INFER_PARAMETER_TYPE on lambda parameters

^KT-56138 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-02-01 13:08:53 +02:00
committed by Space Team
parent 76d360d793
commit f479a56f5e
16 changed files with 126 additions and 18 deletions
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirFieldImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferTypeParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
@@ -458,7 +458,7 @@ internal class KtSymbolByFirBuilder constructor(
is ConeTypeVariableType -> {
val diagnostic = when ( val typeParameter = coneType.lookupTag.originalTypeParameter) {
null -> ConeSimpleDiagnostic("Cannot infer parameter type for ${coneType.lookupTag.debugName}")
else -> ConeCannotInferParameterType((typeParameter as ConeTypeParameterLookupTag).typeParameterSymbol)
else -> ConeCannotInferTypeParameterType((typeParameter as ConeTypeParameterLookupTag).typeParameterSymbol)
}
buildKtType(ConeErrorType(diagnostic, isUninferredParameter = true, attributes = coneType.attributes))
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.types.KtTypeErrorType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferTypeParameterType
import org.jetbrains.kotlin.fir.types.ConeErrorType
import org.jetbrains.kotlin.fir.types.renderForDebugging
@@ -28,7 +28,7 @@ internal class KtFirTypeErrorType(
override fun tryRenderAsNonErrorType(): String? = withValidityAssertion {
when (val diagnostic = coneType.diagnostic) {
is ConeCannotInferParameterType -> diagnostic.typeParameter.name.asString()
is ConeCannotInferTypeParameterType -> diagnostic.typeParameter.name.asString()
else -> null
}
}
@@ -11858,6 +11858,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt51317.kt");
}
@Test
@TestMetadata("kt56138.kt")
public void testKt56138() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt56138.kt");
}
@Test
@TestMetadata("kt6541_extensionForExtensionFunction.kt")
public void testKt6541_extensionForExtensionFunction() throws Exception {
@@ -11864,6 +11864,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt51317.kt");
}
@Test
@TestMetadata("kt56138.kt")
public void testKt56138() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt56138.kt");
}
@Test
@TestMetadata("kt6541_extensionForExtensionFunction.kt")
public void testKt6541_extensionForExtensionFunction() throws Exception {
@@ -11858,6 +11858,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt51317.kt");
}
@Test
@TestMetadata("kt56138.kt")
public void testKt56138() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt56138.kt");
}
@Test
@TestMetadata("kt6541_extensionForExtensionFunction.kt")
public void testKt6541_extensionForExtensionFunction() throws Exception {
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPo
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -109,7 +108,8 @@ private fun ConeDiagnostic.toKtDiagnostic(
}
is ConeDestructuringDeclarationsOnTopLevel -> FirSyntaxErrors.SYNTAX.createOn(source)
is ConeCannotInferParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeCannotInferTypeParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeCannotInferValueParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.createOn(source, this.target)
is ConeStubDiagnostic -> null
is ConeIntermediateDiagnostic -> null
@@ -2318,16 +2318,20 @@ class DeclarationsConverter(
val name = convertValueParameterName(identifier.nameAsSafeName(), identifier, valueParameterDeclaration)
val valueParameterSource = valueParameter.toFirSourceElement()
return ValueParameter(
isVal = isVal,
isVar = isVar,
modifiers = modifiers,
returnTypeRef = firType
?: when {
valueParameterDeclaration == ValueParameterDeclaration.LAMBDA -> buildImplicitTypeRef {
source = valueParameterSource.fakeElement(KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter)
}
valueParameterDeclaration.shouldExplicitParameterTypeBePresent -> createNoTypeForParameterTypeRef()
else -> implicitType
},
source = valueParameter.toFirSourceElement(),
source = valueParameterSource,
moduleData = baseModuleData,
isFromPrimaryConstructor = valueParameterDeclaration == ValueParameterDeclaration.PRIMARY_CONSTRUCTOR,
additionalAnnotations = additionalAnnotations,
@@ -1583,7 +1583,7 @@ open class RawFirBuilder(
multiParameter
} else {
val typeRef = valueParameter.typeReference?.convertSafe() ?: buildImplicitTypeRef {
source = implicitTypeRefSource
source = valueParameter.toFirSourceElement().fakeElement(KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter)
}
convertValueParameter(valueParameter, symbol, typeRef, ValueParameterDeclaration.LAMBDA)
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferTypeParameterType
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
@@ -459,7 +459,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
): ConeErrorType {
val diagnostic = when (typeParameterSymbol) {
null -> ConeSimpleDiagnostic(message, DiagnosticKind.CannotInferParameterType)
else -> ConeCannotInferParameterType(
else -> ConeCannotInferTypeParameterType(
typeParameterSymbol,
message,
)
@@ -332,7 +332,7 @@ class FirCallCompleter(
lambdaArgument.valueParameters.forEachIndexed { index, parameter ->
val newReturnType = parameters[index].approximateLambdaInputType()
val newReturnTypeRef = if (parameter.returnTypeRef is FirImplicitTypeRef) {
newReturnType.toFirResolvedTypeRef(parameter.source)
newReturnType.toFirResolvedTypeRef(parameter.source?.fakeElement(KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter))
} else parameter.returnTypeRef.resolvedTypeFromPrototype(newReturnType)
parameter.replaceReturnTypeRef(newReturnTypeRef)
lookupTracker?.recordTypeResolveAsLookup(newReturnTypeRef, parameter.source, fileSource)
@@ -6,8 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferValueParameterType
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
@@ -85,9 +84,7 @@ fun extractLambdaInfoFromFunctionType(
argumentValueParameters.mapIndexed { index, parameter ->
parameter.returnTypeRef.coneTypeSafe()
?: expectedParameters.getOrNull(index)
?: ConeErrorType(
ConeSimpleDiagnostic("Cannot infer type for parameter ${parameter.name}", DiagnosticKind.CannotInferParameterType)
)
?: ConeErrorType(ConeCannotInferValueParameterType(parameter.symbol))
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.diagnostics
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name
@@ -23,11 +24,16 @@ class ConeUnderscoreIsReserved(source: KtSourceElement) : ConeDiagnosticWithSour
override val reason: String get() = "Names _, __, ___, ..., are reserved in Kotlin"
}
class ConeCannotInferParameterType(
class ConeCannotInferTypeParameterType(
val typeParameter: FirTypeParameterSymbol,
override val reason: String = "Cannot infer type for parameter ${typeParameter.name}"
) : ConeDiagnostic
class ConeCannotInferValueParameterType(
val valueParameter: FirValueParameterSymbol,
override val reason: String = "Cannot infer type for parameter ${valueParameter.name}"
) : ConeDiagnostic
class ConeUnderscoreUsageWithoutBackticks(source: KtSourceElement) : ConeDiagnosticWithSource(source) {
override val reason: String get() = "Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
}
@@ -78,7 +84,7 @@ enum class DiagnosticKind {
Java,
SuperNotAllowed,
ValueParameterWithNoTypeAnnotation,
CannotInferParameterType,
CannotInferParameterType, // TODO: replace this with ConeCannotInferValueParameterType and ConeCannotInferTypeParameterType
IllegalProjectionUsage,
MissingStdlibClass,
NotASupertype,
@@ -248,6 +248,9 @@ sealed class KtFakeSourceElementKind(final override val shouldSkipErrorTypeRepor
// for when on the LHS of an assignment an error expression appears
object AssignmentLValueError : KtFakeSourceElementKind()
// for return type of value parameters in lambdas
object ImplicitReturnTypeOfLambdaValueParameter : KtFakeSourceElementKind()
}
sealed class AbstractKtSourceElement {
@@ -0,0 +1,37 @@
// SKIP_TXT
// ISSUE: KT-56138
fun takeLambda1(f: String.() -> String) {}
fun takeLambda2(f: String.(String) -> String) {}
fun test_1() {
val x1: String.(String) -> String = { str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!> -> "this" }
val x2: String.() -> String = { <!UNRESOLVED_REFERENCE!>it<!> }
val x3: String.() -> String = { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "x" }
}
fun test_2() {
takeLambda2 <!ARGUMENT_TYPE_MISMATCH!>{ str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!> -> "this" }<!>
takeLambda1 { <!UNRESOLVED_REFERENCE!>it<!> }
takeLambda1 <!ARGUMENT_TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "x" }<!>
}
fun test_3(b: Boolean) {
val x1: String.(String) -> String = if (b) {
{ str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!> -> "this" }
} else {
{ str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!> -> "this" }
}
val x2: String.() -> String = if (b) {
{ <!UNRESOLVED_REFERENCE!>it<!> }
} else {
{ <!UNRESOLVED_REFERENCE!>it<!> }
}
val x3: String.() -> String = if (b) {
{ <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "x" }
} else {
{ <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> "x" }
}
}
@@ -0,0 +1,37 @@
// SKIP_TXT
// ISSUE: KT-56138
fun takeLambda1(f: String.() -> String) {}
fun takeLambda2(f: String.(String) -> String) {}
fun test_1() {
val x1: String.(String) -> String = { <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }
val x2: String.() -> String = { <!UNRESOLVED_REFERENCE!>it<!> }
val x3: String.() -> String = { <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>x<!> -> "x" }
}
fun test_2() {
takeLambda2 <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }<!>
takeLambda1 <!TYPE_MISMATCH!>{ <!UNRESOLVED_REFERENCE!>it<!> }<!>
takeLambda1 <!TYPE_MISMATCH!>{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>x<!> -> "x" }<!>
}
fun test_3(b: Boolean) {
val x1: String.(String) -> String = if (b) <!TYPE_MISMATCH!>{
{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }
}<!> else <!TYPE_MISMATCH!>{
{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }
}<!>
val x2: String.() -> String = if (b) <!TYPE_MISMATCH!>{
{ <!UNRESOLVED_REFERENCE!>it<!> }
}<!> else <!TYPE_MISMATCH!>{
{ <!UNRESOLVED_REFERENCE!>it<!> }
}<!>
val x3: String.() -> String = if (b) <!TYPE_MISMATCH!>{
{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>x<!> -> "x" }
}<!> else <!TYPE_MISMATCH!>{
{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>x<!> -> "x" }
}<!>
}
@@ -11864,6 +11864,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt51317.kt");
}
@Test
@TestMetadata("kt56138.kt")
public void testKt56138() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/kt56138.kt");
}
@Test
@TestMetadata("kt6541_extensionForExtensionFunction.kt")
public void testKt6541_extensionForExtensionFunction() throws Exception {