WIP
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt
index 591b9a4..ea70bda 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt
@@ -181,6 +181,16 @@
reportFirDiagnostic(diagnostic, source, data)
}
+ override fun visitAnonymousFunction(
+ anonymousFunction: FirAnonymousFunction,
+ data: CheckerContext,
+ ) {
+ val diagnostic = anonymousFunction.diagnostic ?: return
+ val source = anonymousFunction.source
+
+ reportFirDiagnostic(diagnostic, source, data)
+ }
+
private fun reportFirDiagnostic(
diagnostic: ConeDiagnostic,
source: KtSourceElement?,
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
index 600c25a..4fe0c3f 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
@@ -17,6 +17,7 @@
import org.jetbrains.kotlin.fir.analysis.checkers.projectionKindAsString
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors
+import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.*
@@ -168,7 +169,10 @@
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 ConeCannotInferValueParameterType -> when {
+ isTopLevelLambda -> FirErrors.VALUE_PARAMETER_WITHOUT_EXPLICIT_TYPE.createOn(source)
+ else -> 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)
@@ -316,7 +320,8 @@
rootCause.actualType.removeTypeVariableTypes(typeContext)
},
isMismatchDueToNullability = rootCause.isMismatchDueToNullability,
- candidate = diagnostic.candidate
+ candidate = diagnostic.candidate,
+ rootCause.returnExpressionForLambda,
)
}
@@ -450,30 +455,38 @@
actualType: ConeKotlinType,
isMismatchDueToNullability: Boolean,
candidate: AbstractCallCandidate<*>,
+ returnExpressionForLambda: FirAnonymousFunction?,
): KtDiagnostic {
val symbol = candidate.symbol as FirCallableSymbol
val receiverType = (candidate.chosenExtensionReceiver ?: candidate.dispatchReceiver)?.expression?.resolvedType
- return if (expectedType is ConeCapturedType &&
- expectedType.constructor.projection.kind.let { it == ProjectionKind.OUT || it == ProjectionKind.STAR } &&
- receiverType != null &&
- // Ensure we report an actual argument type mismatch of the candidate and not a lambda return expression
- candidate.argumentMapping.keys.any { it.expression.source == source }
- ) {
- FirErrors.MEMBER_PROJECTED_OUT.createOn(
- source,
- receiverType,
- expectedType.projectionKindAsString(),
- symbol.originalOrSelf(),
- )
- } else {
- FirErrors.ARGUMENT_TYPE_MISMATCH.createOn(
- source,
- expectedType,
- // For lambda expressions, use their resolved type because `rootCause.actualType` can contain unresolved types
- actualType,
- isMismatchDueToNullability
- )
+ return when {
+ returnExpressionForLambda != null ->
+ FirErrors.RETURN_TYPE_MISMATCH.createOn(
+ source, expectedType, actualType, returnExpressionForLambda, isMismatchDueToNullability
+ )
+ expectedType is ConeCapturedType &&
+ expectedType.constructor.projection.kind.let { it == ProjectionKind.OUT || it == ProjectionKind.STAR } &&
+ receiverType != null &&
+ // Ensure we report an actual argument type mismatch of the candidate and not a lambda return expression
+ candidate.argumentMapping.keys.any { it.expression.source == source }
+ -> {
+ FirErrors.MEMBER_PROJECTED_OUT.createOn(
+ source,
+ receiverType,
+ expectedType.projectionKindAsString(),
+ symbol.originalOrSelf(),
+ )
+ }
+ else -> {
+ FirErrors.ARGUMENT_TYPE_MISMATCH.createOn(
+ source,
+ expectedType,
+ // For lambda expressions, use their resolved type because `rootCause.actualType` can contain unresolved types
+ actualType,
+ isMismatchDueToNullability
+ )
+ }
}
}
@@ -564,7 +577,8 @@
expectedType = lowerConeType.removeTypeVariableTypes(typeContext),
actualType = upperConeType.removeTypeVariableTypes(typeContext),
isMismatchDueToNullability = typeMismatchDueToNullability,
- candidate = candidate
+ candidate = candidate,
+ (position as? ConeLambdaArgumentConstraintPosition)?.lambda,
)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ArgumentCheckingProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ArgumentCheckingProcessor.kt
index e8b132e..8f73e60 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ArgumentCheckingProcessor.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ArgumentCheckingProcessor.kt
@@ -9,6 +9,7 @@
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
import org.jetbrains.kotlin.builtins.functions.isBasicFunctionOrKFunction
import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.calls.*
@@ -44,6 +45,7 @@
val context: ResolutionContext,
val isReceiver: Boolean,
val isDispatch: Boolean,
+ val returnExpressionForLambda: FirAnonymousFunction? = null,
) {
val session: FirSession
get() = context.session
@@ -62,9 +64,13 @@
sink: CheckerSink,
context: ResolutionContext,
isReceiver: Boolean,
- isDispatch: Boolean
+ isDispatch: Boolean,
+ returnExpressionForLambda: FirAnonymousFunction? = null,
) {
- val argumentContext = ArgumentContext(candidate, candidate.csBuilder, expectedType, sink, context, isReceiver, isDispatch)
+ val argumentContext = ArgumentContext(
+ candidate, candidate.csBuilder, expectedType, sink, context, isReceiver, isDispatch,
+ returnExpressionForLambda,
+ )
argumentContext.resolveArgumentExpression(atom)
}
@@ -241,7 +247,8 @@
expression,
// Reaching here means argument types mismatch, and we want to record whether it's due to the nullability by checking a subtype
// relation with nullable expected type.
- session.typeContext.isTypeMismatchDueToNullability(argumentType, actualExpectedType)
+ session.typeContext.isTypeMismatchDueToNullability(argumentType, actualExpectedType),
+ returnExpressionForLambda,
)
}
@@ -377,7 +384,8 @@
reportDiagnostic(
ArgumentTypeMismatch(
expectedType, lambdaType, expression,
- context.session.typeContext.isTypeMismatchDueToNullability(lambdaType, expectedType)
+ context.session.typeContext.isTypeMismatchDueToNullability(lambdaType, expectedType),
+ returnExpressionForLambda
)
)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt
index b6f904d..2efcc00 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt
@@ -1013,7 +1013,8 @@
expectedType,
lambdaType,
expression,
- context.session.typeContext.isTypeMismatchDueToNullability(lambdaType, expectedType)
+ context.session.typeContext.isTypeMismatchDueToNullability(lambdaType, expectedType),
+ returnExpressionForLambda = null,
)
)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
index b4b115e..cfbbdc2 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt
@@ -44,6 +44,7 @@
import org.jetbrains.kotlin.resolve.calls.inference.addEqualityConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
+import org.jetbrains.kotlin.resolve.calls.inference.buildCurrentSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
@@ -116,15 +117,7 @@
val finalSubstitutor = readOnlyConstraintStorage
.buildAbstractResultingSubstitutor(session.typeContext) as ConeSubstitutor
call.transformSingle(
- FirCallCompletionResultsWriterTransformer(
- session, components.scopeSession, finalSubstitutor,
- components.returnTypeCalculator,
- session.typeApproximator,
- components.dataFlowAnalyzer,
- components.integerLiteralAndOperatorApproximationTransformer,
- components.samResolver,
- components.context,
- ),
+ createCompletionResultsWriter(finalSubstitutor),
null
)
}
@@ -134,13 +127,24 @@
inferenceSession.processPartiallyResolvedCall(call, resolutionMode, completionMode)
- call
+ if (candidate.isSyntheticCallForTopLevelLambda()) {
+ val finalSubstitutor = candidate.system.currentStorage()
+ .buildCurrentSubstitutor(session.typeContext, emptyMap()) as ConeSubstitutor
+ call.transformSingle(
+ createCompletionResultsWriter(finalSubstitutor),
+ null
+ )
+ } else {
+ call
+ }
}
ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA -> throw IllegalStateException()
}
}
+ private fun Candidate.isSyntheticCallForTopLevelLambda(): Boolean = callInfo.callSite is FirAnonymousFunctionExpression
+
private fun checkStorageConstraintsAfterFullCompletion(storage: ConstraintStorage) {
// Fast path for sake of optimization
if (storage.notFixedTypeVariables.isEmpty()) return
@@ -359,7 +363,7 @@
this.name = name
symbol = FirValueParameterSymbol(name)
returnTypeRef =
- itType.approximateLambdaInputType(symbol, withPCLASession).toFirResolvedTypeRef(
+ itType.approximateLambdaInputType(symbol, withPCLASession, candidate).toFirResolvedTypeRef(
lambdaAtom.anonymousFunction.source?.fakeElement(KtFakeSourceElementKind.ItLambdaParameter)
)
defaultValue = null
@@ -379,7 +383,7 @@
receiverType == null -> lambda.replaceReceiverParameter(null)
!lambdaAtom.coerceFirstParameterToExtensionReceiver -> {
lambda.receiverParameter?.apply {
- val type = receiverType.approximateLambdaInputType(valueParameter = null, withPCLASession)
+ val type = receiverType.approximateLambdaInputType(valueParameter = null, withPCLASession, candidate)
val source =
source?.fakeElement(KtFakeSourceElementKind.LambdaReceiver)
?: lambda.source?.fakeElement(KtFakeSourceElementKind.LambdaReceiver)
@@ -402,7 +406,7 @@
symbol = FirValueParameterSymbol(name)
returnTypeRef = contextParameterType
// TODO(KT-73150) investigate/test the need for approximation
- .approximateLambdaInputType(symbol, withPCLASession)
+ .approximateLambdaInputType(symbol, withPCLASession, candidate)
.toFirResolvedTypeRef(lambdaAtom.anonymousFunction.source?.fakeElement(KtFakeSourceElementKind.LambdaContextParameter))
valueParameterKind = if (session.languageVersionSettings.supportsFeature(LanguageFeature.ContextParameters)) {
FirValueParameterKind.ContextParameter
@@ -437,7 +441,7 @@
)
return@forEachIndexed
}
- val newReturnType = theParameters[index].approximateLambdaInputType(parameter.symbol, withPCLASession)
+ val newReturnType = theParameters[index].approximateLambdaInputType(parameter.symbol, withPCLASession, candidate)
val newReturnTypeRef = if (parameter.returnTypeRef is FirImplicitTypeRef) {
newReturnType.toFirResolvedTypeRef(parameter.source?.fakeElement(KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter))
} else parameter.returnTypeRef.resolvedTypeFromPrototype(newReturnType)
@@ -524,12 +528,15 @@
private fun ConeKotlinType.approximateLambdaInputType(
valueParameter: FirValueParameterSymbol?,
isRootLambdaForPCLASession: Boolean,
+ containingCandidate: Candidate,
): 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 (useErrorTypeInsteadOfTypeVariableForParameterType(isReceiver = valueParameter == null, isRootLambdaForPCLASession)) {
- val diagnostic = valueParameter?.let(::ConeCannotInferValueParameterType) ?: ConeCannotInferReceiverParameterType()
+ val diagnostic = valueParameter?.let {
+ ConeCannotInferValueParameterType(it, isTopLevelLambda = containingCandidate.isSyntheticCallForTopLevelLambda())
+ } ?: ConeCannotInferReceiverParameterType()
return ConeErrorType(diagnostic)
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirPCLAInferenceSession.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirPCLAInferenceSession.kt
index 8026e83..7908e58 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirPCLAInferenceSession.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirPCLAInferenceSession.kt
@@ -71,8 +71,15 @@
currentCommonSystem.replaceContentWith(candidate.system.currentStorage())
- if (completionMode == ConstraintSystemCompletionMode.PCLA_POSTPONED_CALL) {
- outerCandidate.postponedPCLACalls += ConeAtomWithCandidate(call, candidate)
+ when (completionMode) {
+ ConstraintSystemCompletionMode.PCLA_POSTPONED_CALL -> {
+ outerCandidate.postponedPCLACalls += ConeAtomWithCandidate(call, candidate)
+ }
+// ConstraintSystemCompletionMode.PCLA_COMPLETED_NESTED_CALL -> {
+// outerCandidate.postponedPCLACalls += candidate.postponedPCLACalls
+// outerCandidate.lambdasAnalyzedWithPCLA += candidate.lambdasAnalyzedWithPCLA
+// }
+ else -> {}
}
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt
index 5b62b7e..732b507 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArgumentsAnalyzer.kt
@@ -278,7 +278,8 @@
checkerSink,
context = resolutionContext,
isReceiver = false,
- isDispatch = false
+ isDispatch = false,
+ returnExpressionForLambda = lambda.anonymousFunction,
)
}
}
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
index 6c688d8b..b310cfd 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt
@@ -29,6 +29,7 @@
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference
+import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
@@ -245,6 +246,34 @@
.firstOrNull() // TODO: it should be single() after KTIJ-26465 is fixed
}
+ fun resolveAnonymousFunctionExpressionWithSyntheticOuterCall(
+ anonymousFunctionExpression: FirAnonymousFunctionExpression,
+ expectedType: ConeKotlinType?,
+ context: ResolutionContext,
+ ): FirExpression {
+ val argumentList = buildUnaryArgumentList(anonymousFunctionExpression)
+
+ val reference = generateCalleeReferenceToFunctionWithExpectedTypeForArgument(
+ anonymousFunctionExpression,
+ argumentList,
+ expectedType,
+ context,
+ )
+
+ val fakeCall = buildFunctionCall {
+ calleeReference = reference
+ this.argumentList = argumentList
+ }
+
+ val resultingCall = components.callCompleter.completeCall(fakeCall, ResolutionMode.ContextIndependent)
+
+ (resultingCall.calleeReference as? FirResolvedErrorReference)?.let {
+ anonymousFunctionExpression.anonymousFunction.replaceDiagnostic(it.diagnostic)
+ }
+
+ return resultingCall.arguments[0]
+ }
+
fun resolveCallableReferenceWithSyntheticOuterCall(
callableReferenceAccess: FirCallableReferenceAccess,
expectedType: ConeKotlinType?,
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt
index 8dc6614..4592477 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt
@@ -1157,10 +1157,21 @@
private fun transformTopLevelAnonymousFunctionExpression(
anonymousFunctionExpression: FirAnonymousFunctionExpression,
expectedType: ConeKotlinType?,
- ): FirStatement = anonymousFunctionExpression.also {
- it.replaceAnonymousFunction(transformTopLevelAnonymousFunctionInObsoleteWay(anonymousFunctionExpression, expectedType))
+ ): FirStatement = when {
+ session.languageVersionSettings.supportsFeature(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument) ->
+ components.syntheticCallGenerator.resolveAnonymousFunctionExpressionWithSyntheticOuterCall(
+ anonymousFunctionExpression, expectedType, resolutionContext
+ )
+ else -> {
+ @OptIn(OnlyForDefaultLanguageFeatureDisabled::class) // ResolveTopLevelLambdasAsSyntheticCallArgument
+ val updatedAnonymousFunction = transformTopLevelAnonymousFunctionInObsoleteWay(anonymousFunctionExpression, expectedType)
+ anonymousFunctionExpression.replaceAnonymousFunction(updatedAnonymousFunction)
+
+ anonymousFunctionExpression
+ }
}
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
private fun transformTopLevelAnonymousFunctionInObsoleteWay(
anonymousFunctionExpression: FirAnonymousFunctionExpression,
expectedType: ConeKotlinType?
@@ -1235,6 +1246,7 @@
return lambda
}
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
private fun FirAnonymousFunction.computeReturnTypeRef(expected: FirResolvedTypeRef?): FirResolvedTypeRef {
val returnType = computeReturnType(
session,
@@ -1253,6 +1265,37 @@
)
}
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
+ private object ImplicitToErrorTypeTransformer : FirTransformer<Any?>() {
+ override fun <E : FirElement> transformElement(element: E, data: Any?): E {
+ return element
+ }
+
+ override fun transformValueParameter(
+ valueParameter: FirValueParameter,
+ data: Any?
+ ): FirStatement =
+ whileAnalysing(valueParameter.moduleData.session, valueParameter) {
+ if (valueParameter.returnTypeRef is FirImplicitTypeRef) {
+ valueParameter.replaceReturnTypeRef(
+ valueParameter.returnTypeRef.resolvedTypeFromPrototype(
+ ConeErrorType(
+ ConeSimpleDiagnostic(
+ "No type for parameter",
+ DiagnosticKind.ValueParameterWithNoTypeAnnotation
+ )
+ ),
+ fallbackSource = valueParameter.source?.fakeElement(
+ KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter,
+ ),
+ )
+ )
+ }
+ return valueParameter
+ }
+ }
+
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
private fun obtainValueParametersFromResolvedLambdaAtom(
resolvedLambdaAtom: ConeResolvedLambdaAtom,
lambda: FirAnonymousFunction,
@@ -1290,6 +1333,7 @@
}
}
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
private fun obtainValueParametersFromExpectedType(
expectedType: ConeKotlinType?,
lambda: FirAnonymousFunction
@@ -1305,6 +1349,7 @@
return obtainValueParametersFromExpectedParameterTypes(parameterTypes, lambda)
}
+ @OnlyForDefaultLanguageFeatureDisabled(LanguageFeature.ResolveTopLevelLambdasAsSyntheticCallArgument)
private fun obtainValueParametersFromExpectedParameterTypes(
expectedTypeParameterTypes: List<ConeKotlinType>,
lambda: FirAnonymousFunction
@@ -1476,34 +1521,6 @@
}
}
- private object ImplicitToErrorTypeTransformer : FirTransformer<Any?>() {
- override fun <E : FirElement> transformElement(element: E, data: Any?): E {
- return element
- }
-
- override fun transformValueParameter(
- valueParameter: FirValueParameter,
- data: Any?
- ): FirStatement =
- whileAnalysing(valueParameter.moduleData.session, valueParameter) {
- if (valueParameter.returnTypeRef is FirImplicitTypeRef) {
- valueParameter.replaceReturnTypeRef(
- valueParameter.returnTypeRef.resolvedTypeFromPrototype(
- ConeErrorType(
- ConeSimpleDiagnostic(
- "No type for parameter",
- DiagnosticKind.ValueParameterWithNoTypeAnnotation
- )
- ),
- fallbackSource = valueParameter.source?.fakeElement(
- KtFakeSourceElementKind.ImplicitReturnTypeOfLambdaValueParameter,
- ),
- )
- )
- }
- return valueParameter
- }
- }
private val FirVariable.initializerResolved: Boolean
get() {
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
index 88a51d6..7bd16ed 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt
@@ -1234,7 +1234,7 @@
callableReferenceAccess
} else {
components.syntheticCallGenerator.resolveCallableReferenceWithSyntheticOuterCall(
- callableReferenceAccess, data.expectedType, resolutionContext, data
+ callableReferenceAccess, data.expectedType, resolutionContext
)
}.also {
dataFlowAnalyzer.exitCallableReference(it)
diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt
index d23e591..e0b44da 100644
--- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt
+++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt
@@ -135,6 +135,7 @@
val actualType: ConeKotlinType,
val argument: FirExpression,
val isMismatchDueToNullability: Boolean,
+ val returnExpressionForLambda: FirAnonymousFunction? = null,
) : ResolutionDiagnostic(if (isMismatchDueToNullability) UNSAFE_CALL else INAPPLICABLE)
class UnitReturnTypeLambdaContradictsExpectedType(
diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirAnonymousFunction.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirAnonymousFunction.kt
index d23f3c2..adc2f39 100644
--- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirAnonymousFunction.kt
+++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirAnonymousFunction.kt
@@ -14,6 +14,7 @@
import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
+import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
@@ -52,6 +53,7 @@
abstract val hasExplicitParameterList: Boolean
abstract override val typeParameters: List<FirTypeParameter>
abstract val typeRef: FirTypeRef
+ abstract val diagnostic: ConeDiagnostic?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitAnonymousFunction(this, data)
@@ -86,6 +88,8 @@
abstract fun replaceTypeRef(newTypeRef: FirTypeRef)
+ abstract fun replaceDiagnostic(newDiagnostic: ConeDiagnostic?)
+
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
abstract override fun <D> transformStatus(transformer: FirTransformer<D>, data: D): FirAnonymousFunction
diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousFunctionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousFunctionBuilder.kt
index 4afd99e..63f4920 100644
--- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousFunctionBuilder.kt
+++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousFunctionBuilder.kt
@@ -22,6 +22,7 @@
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
+import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
@@ -57,6 +58,7 @@
var hasExplicitParameterList: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
val typeParameters: MutableList<FirTypeParameter> = mutableListOf()
var typeRef: FirTypeRef = FirImplicitTypeRefImplWithoutSource
+ var diagnostic: ConeDiagnostic? = null
override fun build(): FirAnonymousFunction {
return FirAnonymousFunctionImpl(
@@ -84,6 +86,7 @@
hasExplicitParameterList,
typeParameters,
typeRef,
+ diagnostic,
)
}
diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousFunctionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousFunctionImpl.kt
index 63a68e3..2c3e424 100644
--- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousFunctionImpl.kt
+++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousFunctionImpl.kt
@@ -19,6 +19,7 @@
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.declarations.*
+import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
@@ -56,6 +57,7 @@
override val hasExplicitParameterList: Boolean,
override val typeParameters: MutableList<FirTypeParameter>,
override var typeRef: FirTypeRef,
+ override var diagnostic: ConeDiagnostic?,
) : FirAnonymousFunction() {
override val containerSource: DeserializedContainerSource?
get() = null
@@ -194,4 +196,8 @@
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
typeRef = newTypeRef
}
+
+ override fun replaceDiagnostic(newDiagnostic: ConeDiagnostic?) {
+ diagnostic = newDiagnostic
+ }
}
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/annotations.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/annotations.kt
index 812cbee..6de4e20 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/annotations.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/annotations.kt
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir
+import org.jetbrains.kotlin.config.LanguageFeature
+
/**
* [NoMutableState] annotation means that annotated class has no mutable state
* and it's safe to use it concurrent environment (e.g. as session component)
@@ -36,3 +38,11 @@
@RequiresOptIn
annotation class SessionConfiguration
+/**
+ * Declarations that are only being used in case some default language features are disabled: mostly likely due to using not the latest
+ * language version.
+ *
+ * Let's try to have a convention to use a relevant language feature name as a side comment.
+ */
+@RequiresOptIn
+annotation class OnlyForDefaultLanguageFeatureDisabled(val languageFeature: LanguageFeature)
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
index 9d24ed5..fa403bc 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
@@ -40,7 +40,8 @@
class ConeCannotInferValueParameterType(
val valueParameter: FirValueParameterSymbol,
- override val reason: String = "Cannot infer type for parameter ${valueParameter.name}"
+ override val reason: String = "Cannot infer type for parameter ${valueParameter.name}",
+ val isTopLevelLambda: Boolean = false,
) : ConeCannotInferType()
class ConeCannotInferReceiverParameterType(
diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTree.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTree.kt
index 984c192..2cb38f9 100644
--- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTree.kt
+++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTree.kt
@@ -463,6 +463,7 @@
+field("hasExplicitParameterList", boolean)
+typeParameters
+field(typeRef, withReplace = true)
+ +field("diagnostic", coneDiagnosticType, nullable = true, withReplace = true)
}
val anonymousFunctionExpression: Element by element(Expression) {
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
index 7581874..576b2dd 100644
--- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
+++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
@@ -377,6 +377,8 @@
ForbidSyntheticPropertiesWithoutBaseJavaGetter(KOTLIN_2_2, kind = BUG_FIX), // KT-72305, KT-64358
AnnotationDefaultTargetMigrationWarning(KOTLIN_2_2, kind = BUG_FIX), // KT-73255, KT-73494
+ ResolveTopLevelLambdasAsSyntheticCallArgument(KOTLIN_2_1), // KT-67869
+
// 2.3
ForbidCompanionInLocalInnerClass(KOTLIN_2_3, kind = BUG_FIX),