FIR: drop source-based check from InferenceUtils

This commit is contained in:
Mikhail Glukhikh
2021-04-21 13:10:34 +03:00
parent 75d9cd3814
commit e6b9935df9
2 changed files with 15 additions and 11 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
@@ -249,15 +250,15 @@ fun extractLambdaInfoFromFunctionalType(
} }
if (!expectedType.isBuiltinFunctionalType(session)) return null if (!expectedType.isBuiltinFunctionalType(session)) return null
val lastStatement = argument.body?.statements?.singleOrNull() val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
val returnType = if (argument.returnType == null && singleStatement != null &&
singleStatement.target.labeledElement == argument && singleStatement.result is FirUnitExpression
) {
// Simply { }, i.e., function literals without body. Raw FIR added an implicit return with an implicit unit type ref. // Simply { }, i.e., function literals without body. Raw FIR added an implicit return with an implicit unit type ref.
if (lastStatement?.source?.kind is FirFakeSourceElementKind.ImplicitReturn && argument.replaceReturnTypeRef(session.builtinTypes.unitType)
(lastStatement as? FirReturnExpression)?.result?.source?.kind is FirFakeSourceElementKind.ImplicitUnit }
) val returnType = argument.returnType ?: expectedType.returnType(session)
session.builtinTypes.unitType.type
else
argument.returnType ?: expectedType.returnType(session)
// `fun (x: T) = ...` and `fun T.() = ...` are both instances of `T.() -> V` and `(T) -> V`; `fun () = ...` is not. // `fun (x: T) = ...` and `fun T.() = ...` are both instances of `T.() -> V` and `(T) -> V`; `fun () = ...` is not.
// For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter // For lambdas, the existence of the receiver is always implied by the expected type, and a value parameter
// can never fill its role. // can never fill its role.
@@ -269,8 +270,11 @@ fun extractLambdaInfoFromFunctionalType(
expectedParameters // Infer existence of a parameter named `it` of an appropriate type. expectedParameters // Infer existence of a parameter named `it` of an appropriate type.
} else { } else {
argument.valueParameters.mapIndexed { index, parameter -> argument.valueParameters.mapIndexed { index, parameter ->
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index) parameter.returnTypeRef.coneTypeSafe()
?: ConeClassErrorType(ConeSimpleDiagnostic("Cannot infer type for parameter ${parameter.name}", DiagnosticKind.CannotInferParameterType)) ?: expectedParameters.getOrNull(index)
?: ConeClassErrorType(
ConeSimpleDiagnostic("Cannot infer type for parameter ${parameter.name}", DiagnosticKind.CannotInferParameterType)
)
} }
} }
@@ -4,7 +4,7 @@ inline fun <T> tryLambdas(lamb : () -> T) : T{
return lamb.invoke() return lamb.invoke()
} }
fun main() { fun main() {
tryLambdas<String> { <!INAPPLICABLE_CANDIDATE!>tryLambdas<!><String> {
return@tryLambdas return@tryLambdas
} }
} }